home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cdrtools-1.10 / cdrecord / scsi_cdr.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-30  |  66.9 KB  |  2,671 lines

  1. /*
  2. XXX
  3. SIZEOF testen !!!
  4. */
  5. /* @(#)scsi_cdr.c    1.94 00/07/30 Copyright 1995 J. Schilling */
  6. #ifndef lint
  7. static    char sccsid[] =
  8.     "@(#)scsi_cdr.c    1.94 00/07/30 Copyright 1995 J. Schilling";
  9. #endif
  10. /*
  11.  *    SCSI command functions for cdrecord
  12.  *
  13.  *    Copyright (c) 1995 J. Schilling
  14.  */
  15. /*
  16.  * This program is free software; you can redistribute it and/or modify
  17.  * it under the terms of the GNU General Public License as published by
  18.  * the Free Software Foundation; either version 2, or (at your option)
  19.  * any later version.
  20.  *
  21.  * This program is distributed in the hope that it will be useful,
  22.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24.  * GNU General Public License for more details.
  25.  *
  26.  * You should have received a copy of the GNU General Public License
  27.  * along with this program; see the file COPYING.  If not, write to
  28.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  29.  */
  30.  
  31. /*
  32.  * NOTICE:    The Philips CDD 521 has several firmware bugs.
  33.  *        One of them is not to respond to a SCSI selection
  34.  *        within 200ms if the general load on the
  35.  *        SCSI bus is high. To deal with this problem
  36.  *        most of the SCSI commands are send with the
  37.  *        SCG_CMD_RETRY flag enabled.
  38.  */
  39. #include <mconfig.h>
  40.  
  41. #include <stdio.h>
  42. #include <standard.h>
  43. #include <stdxlib.h>
  44. #include <unixstd.h>
  45. #include <fctldefs.h>
  46. #include <errno.h>
  47. #include <strdefs.h>
  48.  
  49. #include <utypes.h>
  50. #include <btorder.h>
  51. #include <intcvt.h>
  52. #include <schily.h>
  53.  
  54. #include <scg/scgcmd.h>
  55. #include <scg/scsidefs.h>
  56. #include <scg/scsireg.h>
  57. #include <scg/scsitransp.h>
  58.  
  59. #include "cdrecord.h"
  60.  
  61. #define    strbeg(s1,s2)    (strstr((s2), (s1)) == (s2))
  62.  
  63. EXPORT    BOOL    unit_ready    __PR((SCSI *scgp));
  64. EXPORT    BOOL    wait_unit_ready    __PR((SCSI *scgp, int secs));
  65. EXPORT    BOOL    scsi_in_progress __PR((SCSI *scgp));
  66. EXPORT    int    test_unit_ready    __PR((SCSI *scgp));
  67. EXPORT    int    rezero_unit    __PR((SCSI *scgp));
  68. EXPORT    int    request_sense    __PR((SCSI *scgp));
  69. EXPORT    int    inquiry        __PR((SCSI *scgp, caddr_t, int));
  70. EXPORT    int    read_capacity    __PR((SCSI *scgp));
  71. EXPORT    int    scsi_load_unload __PR((SCSI *scgp, int));
  72. EXPORT    int    scsi_prevent_removal __PR((SCSI *scgp, int));
  73. EXPORT    int    scsi_start_stop_unit __PR((SCSI *scgp, int, int));
  74. EXPORT    int    scsi_set_speed    __PR((SCSI *scgp, int readspeed, int writespeed));
  75. EXPORT    int    scsi_get_speed    __PR((SCSI *scgp, int *readspeedp, int *writespeedp));
  76. EXPORT    int    qic02        __PR((SCSI *scgp, int));
  77. EXPORT    int    write_xg0    __PR((SCSI *scgp, caddr_t, long, long, int));
  78. EXPORT    int    write_xg1    __PR((SCSI *scgp, caddr_t, long, long, int));
  79. EXPORT    int    write_xg5    __PR((SCSI *scgp, caddr_t, long, long, int));
  80. EXPORT    int    scsi_flush_cache __PR((SCSI *scgp));
  81. EXPORT    int    read_buffer    __PR((SCSI *scgp, caddr_t bp, int cnt, int mode));
  82. EXPORT    int    read_subchannel    __PR((SCSI *scgp, caddr_t bp, int track,
  83.                     int cnt,int msf, int subq, int fmt));
  84. EXPORT    int    read_toc    __PR((SCSI *scgp, caddr_t, int, int, int, int));
  85. EXPORT    int    read_toc_philips __PR((SCSI *scgp, caddr_t, int, int, int, int));
  86. EXPORT    int    read_header    __PR((SCSI *scgp, caddr_t, long, int, int));
  87. EXPORT    int    read_disk_info    __PR((SCSI *scgp, caddr_t, int));
  88. EXPORT    int    read_track_info    __PR((SCSI *scgp, caddr_t, int, int));
  89. EXPORT    int    send_opc    __PR((SCSI *scgp, caddr_t, int cnt, int doopc));
  90. EXPORT    int    read_track_info_philips    __PR((SCSI *scgp, caddr_t, int, int));
  91. EXPORT    int    scsi_close_tr_session __PR((SCSI *scgp, int type, int track, BOOL immed));
  92. EXPORT    int    read_master_cue    __PR((SCSI *scgp, caddr_t bp, int sheet, int cnt));
  93. EXPORT    int    send_cue_sheet    __PR((SCSI *scgp, caddr_t bp, long size));
  94. EXPORT    int    read_buff_cap    __PR((SCSI *scgp, long *, long *));
  95. EXPORT    int    scsi_blank    __PR((SCSI *scgp, long addr, int blanktype, BOOL immed));
  96. EXPORT    BOOL    allow_atapi    __PR((SCSI *scgp, BOOL new));
  97. EXPORT    int    mode_select    __PR((SCSI *scgp, Uchar *, int, int, int));
  98. EXPORT    int    mode_sense    __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
  99. EXPORT    int    mode_select_sg0    __PR((SCSI *scgp, Uchar *, int, int, int));
  100. EXPORT    int    mode_sense_sg0    __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
  101. EXPORT    int    mode_select_g0    __PR((SCSI *scgp, Uchar *, int, int, int));
  102. EXPORT    int    mode_select_g1    __PR((SCSI *scgp, Uchar *, int, int, int));
  103. EXPORT    int    mode_sense_g0    __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
  104. EXPORT    int    mode_sense_g1    __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
  105. EXPORT    int    read_tochdr    __PR((SCSI *scgp, cdr_t *, int *, int *));
  106. EXPORT    int    read_cdtext    __PR((SCSI *scgp));
  107. EXPORT    int    read_trackinfo    __PR((SCSI *scgp, int, long *, struct msf *, int *, int *, int *));
  108. EXPORT    int    read_B0        __PR((SCSI *scgp, BOOL isbcd, long *b0p, long *lop));
  109. EXPORT    int    read_session_offset __PR((SCSI *scgp, long *));
  110. EXPORT    int    read_session_offset_philips __PR((SCSI *scgp, long *));
  111. EXPORT    int    sense_secsize    __PR((SCSI *scgp, int current));
  112. EXPORT    int    select_secsize    __PR((SCSI *scgp, int));
  113. EXPORT    BOOL    is_cddrive    __PR((SCSI *scgp));
  114. EXPORT    BOOL    is_unknown_dev    __PR((SCSI *scgp));
  115. EXPORT    int    read_scsi    __PR((SCSI *scgp, caddr_t, long, int));
  116. EXPORT    int    read_g0        __PR((SCSI *scgp, caddr_t, long, int));
  117. EXPORT    int    read_g1        __PR((SCSI *scgp, caddr_t, long, int));
  118. EXPORT    BOOL    getdev        __PR((SCSI *scgp, BOOL));
  119. EXPORT    void    printdev    __PR((SCSI *scgp));
  120. EXPORT    BOOL    do_inquiry    __PR((SCSI *scgp, BOOL));
  121. EXPORT    BOOL    recovery_needed    __PR((SCSI *scgp));
  122. EXPORT    int    scsi_load    __PR((SCSI *scgp));
  123. EXPORT    int    scsi_unload    __PR((SCSI *scgp));
  124. EXPORT    int    scsi_cdr_write    __PR((SCSI *scgp, caddr_t bp, long sectaddr, long size, int blocks, BOOL islast));
  125. EXPORT    struct cd_mode_page_2A * mmc_cap __PR((SCSI *scgp, Uchar *modep));
  126. EXPORT    void    mmc_getval    __PR((struct cd_mode_page_2A *mp,
  127.                     BOOL *cdrrp, BOOL *cdwrp,
  128.                     BOOL *cdrrwp, BOOL *cdwrwp,
  129.                     BOOL *dvdp));
  130. EXPORT    BOOL    is_mmc        __PR((SCSI *scgp, BOOL *dvdp));
  131. EXPORT    BOOL    mmc_check    __PR((SCSI *scgp, BOOL *cdrrp, BOOL *cdwrp,
  132.                     BOOL *cdrrwp, BOOL *cdwrwp,
  133.                     BOOL *dvdp));
  134. EXPORT    void    print_capabilities __PR((SCSI *scgp));
  135.  
  136. EXPORT BOOL
  137. unit_ready(scgp)
  138.     SCSI    *scgp;
  139. {
  140.     register struct    scg_cmd    *scmd = scgp->scmd;
  141.  
  142.     if (test_unit_ready(scgp) >= 0)        /* alles OK */
  143.         return (TRUE);
  144.     else if (scmd->error >= SCG_FATAL)    /* nicht selektierbar */
  145.         return (FALSE);
  146.  
  147.     if (scmd->sense.code < 0x70) {        /* non extended Sense */
  148.         if (scmd->sense.code == 0x04)    /* NOT_READY */
  149.             return (FALSE);
  150.         return (TRUE);
  151.     }
  152.     if (((struct scsi_ext_sense *)&scmd->sense)->key == SC_UNIT_ATTENTION) {
  153.         if (test_unit_ready(scgp) >= 0)    /* alles OK */
  154.             return (TRUE);
  155.     }
  156.                         /* FALSE wenn NOT_READY */
  157.     return (((struct scsi_ext_sense *)&scmd->sense)->key != SC_NOT_READY);
  158. }
  159.  
  160. EXPORT BOOL
  161. wait_unit_ready(scgp, secs)
  162.     SCSI    *scgp;
  163.     int    secs;
  164. {
  165.     int    i;
  166.     int    c;
  167.     int    k;
  168.     int    ret;
  169.  
  170.     scgp->silent++;
  171.     ret = test_unit_ready(scgp);        /* eat up unit attention */
  172.     if (ret < 0)
  173.         ret = test_unit_ready(scgp);    /* got power on condition? */
  174.     scgp->silent--;
  175.  
  176.     if (ret >= 0)                /* success that's enough */
  177.         return (TRUE);
  178.  
  179.     scgp->silent++;
  180.     for (i=0; i < secs && (ret = test_unit_ready(scgp)) < 0; i++) {
  181.         if (scgp->scmd->scb.busy != 0) {
  182.             sleep(1);
  183.             continue;
  184.         }
  185.         c = scg_sense_code(scgp);
  186.         k = scg_sense_key(scgp);
  187.         if (k == SC_NOT_READY && (c == 0x3A || c == 0x30)) {
  188.             if (scgp->silent <= 1)
  189.                 scg_printerr(scgp);
  190.             scgp->silent--;
  191.             return (FALSE);
  192.         }
  193.         sleep(1);
  194.     }
  195.     scgp->silent--;
  196.     if (ret < 0)
  197.         return (FALSE);
  198.     return (TRUE);
  199. }
  200.  
  201. EXPORT BOOL
  202. scsi_in_progress(scgp)
  203.     SCSI    *scgp;
  204. {
  205.     if (scg_sense_key(scgp) == SC_NOT_READY &&
  206.         /*
  207.          * Logigal unit not ready operation/long_write in progress
  208.          */
  209.         scg_sense_code(scgp) == 0x04 &&
  210.         (scg_sense_qual(scgp) == 0x07 || scg_sense_qual(scgp) == 0x08)) {
  211.         return (TRUE);
  212.     } else {
  213.         if (scgp->silent <= 1)
  214.             scg_printerr(scgp);
  215.     }
  216.     return (FALSE);
  217. }
  218.  
  219. EXPORT int
  220. test_unit_ready(scgp)
  221.     SCSI    *scgp;
  222. {
  223.     register struct    scg_cmd    *scmd = scgp->scmd;
  224.  
  225.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  226.     scmd->addr = (caddr_t)0;
  227.     scmd->size = 0;
  228.     scmd->flags = SCG_DISRE_ENA | (scgp->silent ? SCG_SILENT:0);
  229.     scmd->cdb_len = SC_G0_CDBLEN;
  230.     scmd->sense_len = CCS_SENSE_LEN;
  231.     scmd->target = scgp->target;
  232.     scmd->cdb.g0_cdb.cmd = SC_TEST_UNIT_READY;
  233.     scmd->cdb.g0_cdb.lun = scgp->lun;
  234.     
  235.     scgp->cmdname = "test unit ready";
  236.  
  237.     return (scg_cmd(scgp));
  238. }
  239.  
  240. EXPORT int
  241. rezero_unit(scgp)
  242.     SCSI    *scgp;
  243. {
  244.     register struct    scg_cmd    *scmd = scgp->scmd;
  245.  
  246.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  247.     scmd->addr = (caddr_t)0;
  248.     scmd->size = 0;
  249.     scmd->flags = SCG_DISRE_ENA;
  250.     scmd->cdb_len = SC_G0_CDBLEN;
  251.     scmd->sense_len = CCS_SENSE_LEN;
  252.     scmd->target = scgp->target;
  253.     scmd->cdb.g0_cdb.cmd = SC_REZERO_UNIT;
  254.     scmd->cdb.g0_cdb.lun = scgp->lun;
  255.     
  256.     scgp->cmdname = "rezero unit";
  257.  
  258.     return (scg_cmd(scgp));
  259. }
  260.  
  261. EXPORT int
  262. request_sense(scgp)
  263.     SCSI    *scgp;
  264. {
  265.          char    sensebuf[CCS_SENSE_LEN];
  266.     register struct    scg_cmd    *scmd = scgp->scmd;
  267.  
  268.  
  269.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  270.     scmd->addr = sensebuf;
  271.     scmd->size = sizeof(sensebuf);;
  272.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  273.     scmd->cdb_len = SC_G0_CDBLEN;
  274.     scmd->sense_len = CCS_SENSE_LEN;
  275.     scmd->target = scgp->target;
  276.     scmd->cdb.g0_cdb.cmd = SC_REQUEST_SENSE;
  277.     scmd->cdb.g0_cdb.lun = scgp->lun;
  278.     scmd->cdb.g0_cdb.count = CCS_SENSE_LEN;
  279.     
  280.     scgp->cmdname = "request_sense";
  281.  
  282.     if (scg_cmd(scgp) < 0)
  283.         return (-1);
  284.     scg_prsense((Uchar *)sensebuf, CCS_SENSE_LEN - scg_getresid(scgp));
  285.     return (0);
  286. }
  287.  
  288. EXPORT int
  289. inquiry(scgp, bp, cnt)
  290.     SCSI    *scgp;
  291.     caddr_t    bp;
  292.     int    cnt;
  293. {
  294.     register struct    scg_cmd    *scmd = scgp->scmd;
  295.  
  296.     fillbytes(bp, cnt, '\0');
  297.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  298.     scmd->addr = bp;
  299.     scmd->size = cnt;
  300.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  301.     scmd->cdb_len = SC_G0_CDBLEN;
  302.     scmd->sense_len = CCS_SENSE_LEN;
  303.     scmd->target = scgp->target;
  304.     scmd->cdb.g0_cdb.cmd = SC_INQUIRY;
  305.     scmd->cdb.g0_cdb.lun = scgp->lun;
  306.     scmd->cdb.g0_cdb.count = cnt;
  307.     
  308.     scgp->cmdname = "inquiry";
  309.  
  310.     if (scg_cmd(scgp) < 0)
  311.         return (-1);
  312.     if (scgp->verbose)
  313.         scg_prbytes("Inquiry Data   :", (Uchar *)bp, cnt - scg_getresid(scgp));
  314.     return (0);
  315. }
  316.  
  317. EXPORT int
  318. read_capacity(scgp)
  319.     SCSI    *scgp;
  320. {
  321.     register struct    scg_cmd    *scmd = scgp->scmd;
  322.  
  323.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  324.     scmd->addr = (caddr_t)scgp->cap;
  325.     scmd->size = sizeof(struct scsi_capacity);
  326.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  327.     scmd->cdb_len = SC_G1_CDBLEN;
  328.     scmd->sense_len = CCS_SENSE_LEN;
  329.     scmd->target = scgp->target;
  330.     scmd->cdb.g1_cdb.cmd = 0x25;    /* Read Capacity */
  331.     scmd->cdb.g1_cdb.lun = scgp->lun;
  332.     g1_cdblen(&scmd->cdb.g1_cdb, 0); /* Full Media */
  333.     
  334.     scgp->cmdname = "read capacity";
  335.  
  336.     if (scg_cmd(scgp) < 0) {
  337.         return (-1);
  338.     } else {
  339.         long    kb;
  340.         long    mb;
  341.         long    prmb;
  342.         double    dkb;
  343.         long    cbsize;
  344.         long    cbaddr;
  345.  
  346.         /*
  347.          * c_bsize & c_baddr are signed Int32_t
  348.          * so we use signed int conversion here.
  349.          */
  350.         cbsize = a_to_4_byte(&scgp->cap->c_bsize);
  351.         cbaddr = a_to_4_byte(&scgp->cap->c_baddr);
  352.         scgp->cap->c_bsize = cbsize;
  353.         scgp->cap->c_baddr = cbaddr;
  354.  
  355.         if (scgp->silent)
  356.             return (0);
  357.  
  358.         dkb =  (scgp->cap->c_baddr+1.0) * (scgp->cap->c_bsize/1024.0);
  359.         kb = dkb;
  360.         mb = dkb / 1024.0;
  361.         prmb = dkb / 1000.0 * 1.024;
  362.         printf("Capacity: %ld Blocks = %ld kBytes = %ld MBytes = %ld prMB\n",
  363.             (long)scgp->cap->c_baddr+1, kb, mb, prmb);
  364.         printf("Sectorsize: %ld Bytes\n", (long)scgp->cap->c_bsize);
  365.     }
  366.     return (0);
  367. }
  368.  
  369. EXPORT int
  370. scsi_load_unload(scgp, load)
  371.     SCSI    *scgp;
  372.     int    load;
  373. {
  374.     register struct    scg_cmd    *scmd = scgp->scmd;
  375.  
  376.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  377.     scmd->flags = SCG_DISRE_ENA;
  378.     scmd->cdb_len = SC_G5_CDBLEN;
  379.     scmd->sense_len = CCS_SENSE_LEN;
  380.     scmd->target = scgp->target;
  381.     scmd->cdb.g5_cdb.cmd = 0xA6;
  382.     scmd->cdb.g5_cdb.lun = scgp->lun;
  383.     scmd->cdb.g5_cdb.addr[1] = load?3:2;
  384.     scmd->cdb.g5_cdb.count[2] = 0; /* slot # */
  385.     
  386.     scgp->cmdname = "medium load/unload";
  387.  
  388.     if (scg_cmd(scgp) < 0)
  389.         return (-1);
  390.     return (0);
  391. }
  392.  
  393. EXPORT int
  394. scsi_prevent_removal(scgp, prevent)
  395.     SCSI    *scgp;
  396.     int    prevent;
  397. {
  398.     register struct    scg_cmd    *scmd = scgp->scmd;
  399.  
  400.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  401.     scmd->flags = SCG_DISRE_ENA;
  402.     scmd->cdb_len = SC_G0_CDBLEN;
  403.     scmd->sense_len = CCS_SENSE_LEN;
  404.     scmd->target = scgp->target;
  405.     scmd->cdb.g0_cdb.cmd = 0x1E;
  406.     scmd->cdb.g0_cdb.lun = scgp->lun;
  407.     scmd->cdb.g0_cdb.count = prevent & 1;
  408.     
  409.     scgp->cmdname = "prevent/allow medium removal";
  410.  
  411.     if (scg_cmd(scgp) < 0)
  412.         return (-1);
  413.     return (0);
  414. }
  415.  
  416.  
  417. EXPORT int
  418. scsi_start_stop_unit(scgp, flg, loej)
  419.     SCSI    *scgp;
  420.     int    flg;
  421.     int    loej;
  422. {
  423.     register struct    scg_cmd    *scmd = scgp->scmd;
  424.  
  425.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  426.     scmd->flags = SCG_DISRE_ENA;
  427.     scmd->cdb_len = SC_G0_CDBLEN;
  428.     scmd->sense_len = CCS_SENSE_LEN;
  429.     scmd->target = scgp->target;
  430.     scmd->cdb.g0_cdb.cmd = 0x1B;    /* Start Stop Unit */
  431.     scmd->cdb.g0_cdb.lun = scgp->lun;
  432.     scmd->cdb.g0_cdb.count = (flg ? 1:0) | (loej ? 2:0);
  433.     
  434.     scgp->cmdname = "start/stop unit";
  435.  
  436.     return (scg_cmd(scgp));
  437. }
  438.  
  439. EXPORT int
  440. scsi_set_speed(scgp, readspeed, writespeed)
  441.     SCSI    *scgp;
  442.     int    readspeed;
  443.     int    writespeed;
  444. {
  445.     register struct    scg_cmd    *scmd = scgp->scmd;
  446.  
  447.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  448.     scmd->flags = SCG_DISRE_ENA;
  449.     scmd->cdb_len = SC_G5_CDBLEN;
  450.     scmd->sense_len = CCS_SENSE_LEN;
  451.     scmd->target = scgp->target;
  452.     scmd->cdb.g5_cdb.cmd = 0xBB;
  453.     scmd->cdb.g5_cdb.lun = scgp->lun;
  454.     i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], readspeed);
  455.     i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], writespeed);
  456.  
  457.     scgp->cmdname = "set cd speed";
  458.  
  459.     if (scg_cmd(scgp) < 0)
  460.         return (-1);
  461.     return (0);
  462. }
  463.  
  464. EXPORT int
  465. scsi_get_speed(scgp, readspeedp, writespeedp)
  466.     SCSI    *scgp;
  467.     int    *readspeedp;
  468.     int    *writespeedp;
  469. {
  470.     struct    cd_mode_page_2A *mp;
  471.     Uchar    m[256];
  472.     int    val;
  473.  
  474.     scgp->silent++;
  475.     mp = mmc_cap(scgp, m);/* Get MMC capabilities in allocated mp */
  476.     scgp->silent--;
  477.     if (mp == NULL)
  478.         return (-1);    /* Pre SCSI-3/mmc drive         */
  479.  
  480.     val = a_to_u_2_byte(mp->cur_read_speed);
  481.     if (readspeedp)
  482.         *readspeedp = val;
  483.  
  484.     val = a_to_u_2_byte(mp->cur_write_speed);
  485.     if (writespeedp)
  486.         *writespeedp = val;
  487.  
  488.     return (0);
  489. }
  490.  
  491.  
  492. EXPORT int
  493. qic02(scgp, cmd)
  494.     SCSI    *scgp;
  495.     int    cmd;
  496. {
  497.     register struct    scg_cmd    *scmd = scgp->scmd;
  498.  
  499.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  500.     scmd->addr = (caddr_t)0;
  501.     scmd->size = 0;
  502.     scmd->flags = SCG_DISRE_ENA;
  503.     scmd->cdb_len = SC_G0_CDBLEN;
  504.     scmd->sense_len = DEF_SENSE_LEN;
  505.     scmd->target = scgp->target;
  506.     scmd->cdb.g0_cdb.cmd = 0x0D;    /* qic02 Sysgen SC4000 */
  507.     scmd->cdb.g0_cdb.lun = scgp->lun;
  508.     scmd->cdb.g0_cdb.mid_addr = cmd;
  509.     
  510.     scgp->cmdname = "qic 02";
  511.     return (scg_cmd(scgp));
  512. }
  513.  
  514. EXPORT int
  515. write_xg0(scgp, bp, addr, size, cnt)
  516.     SCSI    *scgp;
  517.     caddr_t    bp;        /* address of buffer */
  518.     long    addr;        /* disk address (sector) to put */
  519.     long    size;        /* number of bytes to transfer */
  520.     int    cnt;        /* sectorcount */
  521. {
  522.     register struct    scg_cmd    *scmd = scgp->scmd;
  523.  
  524.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  525.     scmd->addr = bp;
  526.     scmd->size = size;
  527.     scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
  528. /*    scmd->flags = SCG_DISRE_ENA;*/
  529.     scmd->cdb_len = SC_G0_CDBLEN;
  530.     scmd->sense_len = CCS_SENSE_LEN;
  531.     scmd->target = scgp->target;
  532.     scmd->cdb.g0_cdb.cmd = SC_WRITE;
  533.     scmd->cdb.g0_cdb.lun = scgp->lun;
  534.     g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
  535.     scmd->cdb.g0_cdb.count = cnt;
  536.     
  537.     scgp->cmdname = "write_g0";
  538.  
  539.     if (scg_cmd(scgp) < 0)
  540.         return (-1);
  541.     return (size - scg_getresid(scgp));
  542. }
  543.  
  544. EXPORT int
  545. write_xg1(scgp, bp, addr, size, cnt)
  546.     SCSI    *scgp;
  547.     caddr_t    bp;        /* address of buffer */
  548.     long    addr;        /* disk address (sector) to put */
  549.     long    size;        /* number of bytes to transfer */
  550.     int    cnt;        /* sectorcount */
  551. {
  552.     register struct    scg_cmd    *scmd = scgp->scmd;
  553.  
  554.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  555.     scmd->addr = bp;
  556.     scmd->size = size;
  557.     scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
  558. /*    scmd->flags = SCG_DISRE_ENA;*/
  559.     scmd->cdb_len = SC_G1_CDBLEN;
  560.     scmd->sense_len = CCS_SENSE_LEN;
  561.     scmd->target = scgp->target;
  562.     scmd->cdb.g1_cdb.cmd = SC_EWRITE;
  563.     scmd->cdb.g1_cdb.lun = scgp->lun;
  564.     g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
  565.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  566.     
  567.     scgp->cmdname = "write_g1";
  568.  
  569.     if (scg_cmd(scgp) < 0)
  570.         return (-1);
  571.     return (size - scg_getresid(scgp));
  572. }
  573.  
  574. EXPORT int
  575. write_xg5(scgp, bp, addr, size, cnt)
  576.     SCSI    *scgp;
  577.     caddr_t    bp;        /* address of buffer */
  578.     long    addr;        /* disk address (sector) to put */
  579.     long    size;        /* number of bytes to transfer */
  580.     int    cnt;        /* sectorcount */
  581. {
  582.     register struct    scg_cmd    *scmd = scgp->scmd;
  583.  
  584.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  585.     scmd->addr = bp;
  586.     scmd->size = size;
  587.     scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
  588. /*    scmd->flags = SCG_DISRE_ENA;*/
  589.     scmd->cdb_len = SC_G5_CDBLEN;
  590.     scmd->sense_len = CCS_SENSE_LEN;
  591.     scmd->target = scgp->target;
  592.     scmd->cdb.g5_cdb.cmd = 0xAA;
  593.     scmd->cdb.g5_cdb.lun = scgp->lun;
  594.     g5_cdbaddr(&scmd->cdb.g5_cdb, addr);
  595.     g5_cdblen(&scmd->cdb.g5_cdb, cnt);
  596.     
  597.     scgp->cmdname = "write_g5";
  598.  
  599.     if (scg_cmd(scgp) < 0)
  600.         return (-1);
  601.     return (size - scg_getresid(scgp));
  602. }
  603.  
  604. EXPORT int
  605. scsi_flush_cache(scgp)
  606.     SCSI    *scgp;
  607. {
  608.     register struct    scg_cmd    *scmd = scgp->scmd;
  609.  
  610.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  611.     scmd->flags = SCG_DISRE_ENA;
  612.     scmd->cdb_len = SC_G1_CDBLEN;
  613.     scmd->sense_len = CCS_SENSE_LEN;
  614.     scmd->target = scgp->target;
  615.     scmd->timeout = 2 * 60;        /* Max: sizeof(CDR-cache)/150KB/s */
  616.     scmd->cdb.g1_cdb.cmd = 0x35;
  617.     scmd->cdb.g1_cdb.lun = scgp->lun;
  618.     
  619.     scgp->cmdname = "flush cache";
  620.  
  621.     if (scg_cmd(scgp) < 0)
  622.         return (-1);
  623.     return (0);
  624. }
  625.  
  626. EXPORT int
  627. read_buffer(scgp, bp, cnt, mode)
  628.     SCSI    *scgp;
  629.     caddr_t    bp;
  630.     int    cnt;
  631.     int    mode;
  632. {
  633.     register struct    scg_cmd    *scmd = scgp->scmd;
  634.  
  635.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  636.     scmd->addr = bp;
  637.     scmd->size = cnt;
  638.     scmd->dma_read = 1;
  639.     scmd->cdb_len = SC_G1_CDBLEN;
  640.     scmd->sense_len = CCS_SENSE_LEN;
  641.     scmd->target = scgp->target;
  642.     scmd->cdb.g1_cdb.cmd = 0x3C;    /* Read Buffer */
  643.     scmd->cdb.g1_cdb.lun = scgp->lun;
  644.     scmd->cdb.cmd_cdb[1] |= (mode & 7);
  645.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  646.     
  647.     scgp->cmdname = "read buffer";
  648.  
  649.     return (scg_cmd(scgp));
  650. }
  651.  
  652. EXPORT int
  653. read_subchannel(scgp, bp, track, cnt, msf, subq, fmt)
  654.     SCSI    *scgp;
  655.     caddr_t    bp;
  656.     int    track;
  657.     int    cnt;
  658.     int    msf;
  659.     int    subq;
  660.     int    fmt;
  661.  
  662. {
  663.     register struct    scg_cmd    *scmd = scgp->scmd;
  664.  
  665.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  666.     scmd->addr = bp;
  667.     scmd->size = cnt;
  668.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  669.     scmd->cdb_len = SC_G1_CDBLEN;
  670.     scmd->sense_len = CCS_SENSE_LEN;
  671.     scmd->target = scgp->target;
  672.     scmd->cdb.g1_cdb.cmd = 0x42;
  673.     scmd->cdb.g1_cdb.lun = scgp->lun;
  674.     if (msf)
  675.         scmd->cdb.g1_cdb.res = 1;
  676.     if (subq)
  677.         scmd->cdb.g1_cdb.addr[0] = 0x40;
  678.     scmd->cdb.g1_cdb.addr[1] = fmt;
  679.     scmd->cdb.g1_cdb.res6 = track;
  680.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  681.  
  682.     scgp->cmdname = "read subchannel";
  683.  
  684.     if (scg_cmd(scgp) < 0)
  685.         return (-1);
  686.     return (0);
  687. }
  688.  
  689. EXPORT int
  690. read_toc(scgp, bp, track, cnt, msf, fmt)
  691.     SCSI    *scgp;
  692.     caddr_t    bp;
  693.     int    track;
  694.     int    cnt;
  695.     int    msf;
  696.     int    fmt;
  697.  
  698. {
  699.     register struct    scg_cmd    *scmd = scgp->scmd;
  700.  
  701.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  702.     scmd->addr = bp;
  703.     scmd->size = cnt;
  704.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  705.     scmd->cdb_len = SC_G1_CDBLEN;
  706.     scmd->sense_len = CCS_SENSE_LEN;
  707.     scmd->target = scgp->target;
  708.     scmd->cdb.g1_cdb.cmd = 0x43;
  709.     scmd->cdb.g1_cdb.lun = scgp->lun;
  710.     if (msf)
  711.         scmd->cdb.g1_cdb.res = 1;
  712.     scmd->cdb.g1_cdb.addr[0] = fmt & 0x0F;
  713.     scmd->cdb.g1_cdb.res6 = track;
  714.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  715.  
  716.     scgp->cmdname = "read toc";
  717.  
  718.     if (scg_cmd(scgp) < 0)
  719.         return (-1);
  720.     return (0);
  721. }
  722.  
  723. EXPORT int
  724. read_toc_philips(scgp, bp, track, cnt, msf, fmt)
  725.     SCSI    *scgp;
  726.     caddr_t    bp;
  727.     int    track;
  728.     int    cnt;
  729.     int    msf;
  730.     int    fmt;
  731.  
  732. {
  733.     register struct    scg_cmd    *scmd = scgp->scmd;
  734.  
  735.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  736.     scmd->addr = bp;
  737.     scmd->size = cnt;
  738.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  739.     scmd->cdb_len = SC_G1_CDBLEN;
  740.     scmd->sense_len = CCS_SENSE_LEN;
  741.     scmd->target = scgp->target;
  742.     scmd->timeout = 4 * 60;        /* May last  174s on a TEAC CD-R55S */
  743.     scmd->cdb.g1_cdb.cmd = 0x43;
  744.     scmd->cdb.g1_cdb.lun = scgp->lun;
  745.     if (msf)
  746.         scmd->cdb.g1_cdb.res = 1;
  747.     scmd->cdb.g1_cdb.res6 = track;
  748.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  749.  
  750.     if (fmt & 1)
  751.         scmd->cdb.g1_cdb.vu_96 = 1;
  752.     if (fmt & 2)
  753.         scmd->cdb.g1_cdb.vu_97 = 1;
  754.  
  755.     scgp->cmdname = "read toc";
  756.  
  757.     if (scg_cmd(scgp) < 0)
  758.         return (-1);
  759.     return (0);
  760. }
  761.  
  762. EXPORT int
  763. read_header(scgp, bp, addr, cnt, msf)
  764.     SCSI    *scgp;
  765.     caddr_t    bp;
  766.     long    addr;
  767.     int    cnt;
  768.     int    msf;
  769. {
  770.     register struct    scg_cmd    *scmd = scgp->scmd;
  771.  
  772.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  773.     scmd->addr = bp;
  774.     scmd->size = cnt;
  775.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  776.     scmd->cdb_len = SC_G1_CDBLEN;
  777.     scmd->sense_len = CCS_SENSE_LEN;
  778.     scmd->target = scgp->target;
  779.     scmd->cdb.g1_cdb.cmd = 0x44;
  780.     scmd->cdb.g1_cdb.lun = scgp->lun;
  781.     if (msf)
  782.         scmd->cdb.g1_cdb.res = 1;
  783.     g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
  784.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  785.  
  786.     scgp->cmdname = "read header";
  787.  
  788.     if (scg_cmd(scgp) < 0)
  789.         return (-1);
  790.     return (0);
  791. }
  792.  
  793. EXPORT int
  794. read_disk_info(scgp, bp, cnt)
  795.     SCSI    *scgp;
  796.     caddr_t    bp;
  797.     int    cnt;
  798.  
  799. {
  800.     register struct    scg_cmd    *scmd = scgp->scmd;
  801.  
  802.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  803.     scmd->addr = bp;
  804.     scmd->size = cnt;
  805.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  806.     scmd->cdb_len = SC_G1_CDBLEN;
  807.     scmd->sense_len = CCS_SENSE_LEN;
  808.     scmd->target = scgp->target;
  809.     scmd->timeout = 4 * 60;        /* Needs up to 2 minutes */
  810.     scmd->cdb.g1_cdb.cmd = 0x51;
  811.     scmd->cdb.g1_cdb.lun = scgp->lun;
  812.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  813.  
  814.     scgp->cmdname = "read disk info";
  815.  
  816.     if (scg_cmd(scgp) < 0)
  817.         return (-1);
  818.     return (0);
  819. }
  820.  
  821. EXPORT int
  822. read_track_info(scgp, bp, track, cnt)
  823.     SCSI    *scgp;
  824.     caddr_t    bp;
  825.     int    track;
  826.     int    cnt;
  827.  
  828. {
  829.     register struct    scg_cmd    *scmd = scgp->scmd;
  830.  
  831.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  832.     scmd->addr = bp;
  833.     scmd->size = cnt;
  834.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  835.     scmd->cdb_len = SC_G1_CDBLEN;
  836.     scmd->sense_len = CCS_SENSE_LEN;
  837.     scmd->target = scgp->target;
  838.     scmd->timeout = 4 * 60;        /* Needs up to 2 minutes */
  839.     scmd->cdb.g1_cdb.cmd = 0x52;
  840.     scmd->cdb.g1_cdb.lun = scgp->lun;
  841.     scmd->cdb.g1_cdb.reladr = 1;    /* Track */
  842.     g1_cdbaddr(&scmd->cdb.g1_cdb, track);
  843.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  844.  
  845.     scgp->cmdname = "read track info";
  846.  
  847.     if (scg_cmd(scgp) < 0)
  848.         return (-1);
  849.     return (0);
  850. }
  851.  
  852. EXPORT int
  853. send_opc(scgp, bp, cnt, doopc)
  854.     SCSI    *scgp;
  855.     caddr_t    bp;
  856.     int    cnt;
  857.     int    doopc;
  858. {
  859.     register struct    scg_cmd    *scmd = scgp->scmd;
  860.  
  861.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  862.     scmd->addr = bp;
  863.     scmd->size = cnt;
  864.     scmd->flags = SCG_DISRE_ENA;
  865.     scmd->cdb_len = SC_G1_CDBLEN;
  866.     scmd->sense_len = CCS_SENSE_LEN;
  867.     scmd->target = scgp->target;
  868.     scmd->timeout = 60;
  869.     scmd->cdb.g1_cdb.cmd = 0x54;
  870.     scmd->cdb.g1_cdb.lun = scgp->lun;
  871.     scmd->cdb.g1_cdb.reladr = doopc?1:0;
  872.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  873.  
  874.     scgp->cmdname = "send opc";
  875.  
  876.     if (scg_cmd(scgp) < 0)
  877.         return (-1);
  878.     return (0);
  879. }
  880.  
  881. EXPORT int
  882. read_track_info_philips(scgp, bp, track, cnt)
  883.     SCSI    *scgp;
  884.     caddr_t    bp;
  885.     int    track;
  886.     int    cnt;
  887.  
  888. {
  889.     register struct    scg_cmd    *scmd = scgp->scmd;
  890.  
  891.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  892.     scmd->addr = bp;
  893.     scmd->size = cnt;
  894.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  895.     scmd->cdb_len = SC_G1_CDBLEN;
  896.     scmd->sense_len = CCS_SENSE_LEN;
  897.     scmd->target = scgp->target;
  898.     scmd->cdb.g1_cdb.cmd = 0xE5;
  899.     scmd->cdb.g1_cdb.lun = scgp->lun;
  900.     g1_cdbaddr(&scmd->cdb.g1_cdb, track);
  901.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  902.  
  903.     scgp->cmdname = "read track info";
  904.  
  905.     if (scg_cmd(scgp) < 0)
  906.         return (-1);
  907.     return (0);
  908. }
  909.  
  910. EXPORT int
  911. scsi_close_tr_session(scgp, type, track, immed)
  912.     SCSI    *scgp;
  913.     int    type;
  914.     int    track;
  915.     BOOL    immed;
  916. {
  917.     register struct    scg_cmd    *scmd = scgp->scmd;
  918.  
  919.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  920.     scmd->flags = SCG_DISRE_ENA;
  921.     scmd->cdb_len = SC_G1_CDBLEN;
  922.     scmd->sense_len = CCS_SENSE_LEN;
  923.     scmd->target = scgp->target;
  924.     scmd->timeout = 8 * 60;        /* Needs up to 4 minutes */
  925.     scmd->cdb.g1_cdb.cmd = 0x5B;
  926.     scmd->cdb.g1_cdb.lun = scgp->lun;
  927.     scmd->cdb.g1_cdb.addr[0] = type;
  928.     scmd->cdb.g1_cdb.addr[3] = track;
  929.  
  930.     if (immed)
  931.         scmd->cdb.g1_cdb.reladr = 1;
  932. #ifdef    nono
  933.     scmd->cdb.g1_cdb.reladr = 1;    /* IMM hack to test Mitsumi behaviour*/
  934. #endif
  935.     
  936.     scgp->cmdname = "close track/session";
  937.  
  938.     if (scg_cmd(scgp) < 0)
  939.         return (-1);
  940.     return (0);
  941. }
  942.  
  943. EXPORT int
  944. read_master_cue(scgp, bp, sheet, cnt)
  945.     SCSI    *scgp;
  946.     caddr_t    bp;        /* address of master cue sheet    */
  947.     int    sheet;        /* Sheet number            */
  948.     int    cnt;        /* Transfer count        */
  949. {
  950.     register struct    scg_cmd    *scmd = scgp->scmd;
  951.  
  952.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  953.     scmd->addr = bp;
  954.     scmd->size = cnt;
  955.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  956.     scmd->cdb_len = SC_G1_CDBLEN;
  957.     scmd->sense_len = CCS_SENSE_LEN;
  958.     scmd->target = scgp->target;
  959.     scmd->cdb.g1_cdb.cmd = 0x59;        /* Read master cue */
  960.     scmd->cdb.g1_cdb.lun = scgp->lun;
  961.     scmd->cdb.g1_cdb.addr[2] = sheet;
  962.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  963.  
  964.     scgp->cmdname = "read master cue";
  965.  
  966.     if (scg_cmd(scgp) < 0)
  967.         return (-1);
  968.     return (0);
  969. }
  970.  
  971. EXPORT int
  972. send_cue_sheet(scgp, bp, size)
  973.     SCSI    *scgp;
  974.     caddr_t    bp;        /* address of cue sheet buffer */
  975.     long    size;        /* number of bytes to transfer */
  976. {
  977.     register struct    scg_cmd    *scmd = scgp->scmd;
  978.  
  979.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  980.     scmd->addr = bp;
  981.     scmd->size = size;
  982.     scmd->flags = SCG_DISRE_ENA;
  983.     scmd->cdb_len = SC_G1_CDBLEN;
  984.     scmd->sense_len = CCS_SENSE_LEN;
  985.     scmd->target = scgp->target;
  986.     scmd->cdb.g1_cdb.cmd = 0x5D;    /* Send CUE sheet */
  987.     scmd->cdb.g1_cdb.lun = scgp->lun;
  988.     g1_cdblen(&scmd->cdb.g1_cdb, size); 
  989.  
  990.     scgp->cmdname = "send_cue_sheet";
  991.  
  992.     if (scg_cmd(scgp) < 0)
  993.         return (-1);
  994.     return (size - scmd->resid);
  995. }
  996.  
  997. EXPORT int
  998. read_buff_cap(scgp, sp, fp)
  999.     SCSI    *scgp;
  1000.     long    *sp;    /* Size pointer */
  1001.     long    *fp;    /* Free pointer */
  1002. {
  1003.     char    resp[12];
  1004.     Ulong    freespace;
  1005.     Ulong    bufsize;
  1006.     int    per;
  1007.     register struct    scg_cmd    *scmd = scgp->scmd;
  1008.  
  1009.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  1010.     scmd->addr = (caddr_t)resp;
  1011.     scmd->size = sizeof(resp);
  1012.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  1013.     scmd->cdb_len = SC_G1_CDBLEN;
  1014.     scmd->sense_len = CCS_SENSE_LEN;
  1015.     scmd->target = scgp->target;
  1016.     scmd->cdb.g1_cdb.cmd = 0x5C;        /* Read buffer cap */
  1017.     scmd->cdb.g1_cdb.lun = scgp->lun;
  1018.     g1_cdblen(&scmd->cdb.g1_cdb, sizeof(resp));
  1019.     
  1020.     scgp->cmdname = "read buffer cap";
  1021.  
  1022.     if (scg_cmd(scgp) < 0)
  1023.         return (-1);
  1024.  
  1025.     bufsize   = a_to_u_4_byte(&resp[4]);
  1026.     freespace = a_to_u_4_byte(&resp[8]);
  1027.     if (sp)
  1028.         *sp = bufsize;
  1029.     if (fp)
  1030.         *fp = freespace;
  1031.     
  1032.     if (scgp->verbose || (sp == 0 && fp == 0))
  1033.         printf("BFree: %ld K BSize: %ld K\n", freespace >> 10, bufsize >> 10);
  1034.  
  1035.     if (bufsize == 0)
  1036.         return (0);
  1037.     per = (100 * (bufsize - freespace)) / bufsize;
  1038.     if (per < 0)
  1039.         return (0);
  1040.     if (per > 100)
  1041.         return (100);
  1042.     return (per);
  1043. }
  1044.  
  1045. EXPORT int
  1046. scsi_blank(scgp, addr, blanktype, immed)
  1047.     SCSI    *scgp;
  1048.     long    addr;
  1049.     int    blanktype;
  1050.     BOOL    immed;
  1051. {
  1052.     register struct    scg_cmd    *scmd = scgp->scmd;
  1053.  
  1054.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  1055.     scmd->flags = SCG_DISRE_ENA;
  1056.     scmd->cdb_len = SC_G5_CDBLEN;
  1057.     scmd->sense_len = CCS_SENSE_LEN;
  1058.     scmd->target = scgp->target;
  1059.     scmd->timeout = 160 * 60; /* full blank at 1x could take 80 minutes */
  1060.     scmd->cdb.g5_cdb.cmd = 0xA1;    /* Blank */
  1061.     scmd->cdb.g0_cdb.high_addr = blanktype;
  1062.     g1_cdbaddr(&scmd->cdb.g5_cdb, addr);
  1063.  
  1064.     if (immed)
  1065.         scmd->cdb.g5_cdb.res |= 8;
  1066.  
  1067.     scgp->cmdname = "blank unit";
  1068.  
  1069.     return (scg_cmd(scgp));
  1070. }
  1071.  
  1072. /*
  1073.  * XXX First try to handle ATAPI:
  1074.  * XXX ATAPI cannot handle SCSI 6 byte commands.
  1075.  * XXX We try to simulate 6 byte mode sense/select.
  1076.  */
  1077. LOCAL BOOL    is_atapi;
  1078.  
  1079. EXPORT BOOL
  1080. allow_atapi(scgp, new)
  1081.     SCSI    *scgp;
  1082.     BOOL    new;
  1083. {
  1084.     BOOL    old = is_atapi;
  1085.     Uchar    mode[256];
  1086.  
  1087.     if (new == old)
  1088.         return (old);
  1089.  
  1090.     scgp->silent++;
  1091.     if (new &&
  1092.         mode_sense_g1(scgp, mode, 8, 0x3F, 0) < 0) {    /* All pages current */
  1093.         new = FALSE;
  1094.     }
  1095.     scgp->silent--;
  1096.  
  1097.     is_atapi = new;
  1098.     return (old);
  1099. }
  1100.  
  1101. EXPORT int
  1102. mode_select(scgp, dp, cnt, smp, pf)
  1103.     SCSI    *scgp;
  1104.     Uchar    *dp;
  1105.     int    cnt;
  1106.     int    smp;
  1107.     int    pf;
  1108. {
  1109.     if (is_atapi)
  1110.         return (mode_select_sg0(scgp, dp, cnt, smp, pf));
  1111.     return (mode_select_g0(scgp, dp, cnt, smp, pf));
  1112. }
  1113.  
  1114. EXPORT int
  1115. mode_sense(scgp, dp, cnt, page, pcf)
  1116.     SCSI    *scgp;
  1117.     Uchar    *dp;
  1118.     int    cnt;
  1119.     int    page;
  1120.     int    pcf;
  1121. {
  1122.     if (is_atapi)
  1123.         return (mode_sense_sg0(scgp, dp, cnt, page, pcf));
  1124.     return (mode_sense_g0(scgp, dp, cnt, page, pcf));
  1125. }
  1126.  
  1127. /*
  1128.  * Simulate mode select g0 with mode select g1.
  1129.  */
  1130. EXPORT int
  1131. mode_select_sg0(scgp, dp, cnt, smp, pf)
  1132.     SCSI    *scgp;
  1133.     Uchar    *dp;
  1134.     int    cnt;
  1135.     int    smp;
  1136.     int    pf;
  1137. {
  1138.     Uchar    xmode[256+4];
  1139.     int    amt = cnt;
  1140.  
  1141.     if (amt < 1 || amt > 255) {
  1142.         /* XXX clear SCSI error codes ??? */
  1143.         return (-1);
  1144.     }
  1145.  
  1146.     if (amt < 4) {        /* Data length. medium type & VU */
  1147.         amt += 1;
  1148.     } else {
  1149.         amt += 4;
  1150.         movebytes(&dp[4], &xmode[8], cnt-4);
  1151.     }
  1152.     xmode[0] = 0;
  1153.     xmode[1] = 0;
  1154.     xmode[2] = dp[1];
  1155.     xmode[3] = dp[2];
  1156.     xmode[4] = 0;
  1157.     xmode[5] = 0;
  1158.     i_to_2_byte(&xmode[6], (unsigned int)dp[3]);
  1159.  
  1160.     if (scgp->verbose) scg_prbytes("Mode Parameters (un-converted)", dp, cnt);
  1161.  
  1162.     return (mode_select_g1(scgp, xmode, amt, smp, pf));
  1163. }
  1164.  
  1165. /*
  1166.  * Simulate mode sense g0 with mode sense g1.
  1167.  */
  1168. EXPORT int
  1169. mode_sense_sg0(scgp, dp, cnt, page, pcf)
  1170.     SCSI    *scgp;
  1171.     Uchar    *dp;
  1172.     int    cnt;
  1173.     int    page;
  1174.     int    pcf;
  1175. {
  1176.     Uchar    xmode[256+4];
  1177.     int    amt = cnt;
  1178.     int    len;
  1179.  
  1180.     if (amt < 1 || amt > 255) {
  1181.         /* XXX clear SCSI error codes ??? */
  1182.         return (-1);
  1183.     }
  1184.  
  1185.     fillbytes((caddr_t)xmode, sizeof(xmode), '\0');
  1186.     if (amt < 4) {        /* Data length. medium type & VU */
  1187.         amt += 1;
  1188.     } else {
  1189.         amt += 4;
  1190.     }
  1191.     if (mode_sense_g1(scgp, xmode, amt, page, pcf) < 0)
  1192.         return (-1);
  1193.  
  1194.     amt = cnt - scg_getresid(scgp);
  1195. /*
  1196.  * For tests: Solaris 8 & LG CD-ROM always returns resid == amt
  1197.  */
  1198. /*    amt = cnt;*/
  1199.     if (amt > 4)
  1200.         movebytes(&xmode[8], &dp[4], amt-4);
  1201.     len = a_to_u_2_byte(xmode);
  1202.     if (len == 0) {
  1203.         dp[0] = 0;
  1204.     } else if (len < 6) {
  1205.         if (len > 2)
  1206.             len = 2;
  1207.         dp[0] = len;
  1208.     } else {
  1209.         dp[0] = len - 3;
  1210.     }
  1211.     dp[1] = xmode[2];
  1212.     dp[2] = xmode[3];
  1213.     len = a_to_u_2_byte(&xmode[6]);
  1214.     dp[3] = len;
  1215.  
  1216.     if (scgp->verbose) scg_prbytes("Mode Sense Data (converted)", dp, amt);
  1217.     return (0);
  1218. }
  1219.  
  1220. EXPORT int
  1221. mode_select_g0(scgp, dp, cnt, smp, pf)
  1222.     SCSI    *scgp;
  1223.     Uchar    *dp;
  1224.     int    cnt;
  1225.     int    smp;
  1226.     int    pf;
  1227. {
  1228.     register struct    scg_cmd    *scmd = scgp->scmd;
  1229.  
  1230.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  1231.     scmd->addr = (caddr_t)dp;
  1232.     scmd->size = cnt;
  1233.     scmd->flags = SCG_DISRE_ENA;
  1234.     scmd->cdb_len = SC_G0_CDBLEN;
  1235.     scmd->sense_len = CCS_SENSE_LEN;
  1236.     scmd->target = scgp->target;
  1237.     scmd->cdb.g0_cdb.cmd = SC_MODE_SELECT;
  1238.     scmd->cdb.g0_cdb.lun = scgp->lun;
  1239.     scmd->cdb.g0_cdb.high_addr = smp ? 1 : 0 | pf ? 0x10 : 0;
  1240.     scmd->cdb.g0_cdb.count = cnt;
  1241.  
  1242.     if (scgp->verbose) {
  1243.         printf("%s ", smp?"Save":"Set ");
  1244.         scg_prbytes("Mode Parameters", dp, cnt);
  1245.     }
  1246.  
  1247.     scgp->cmdname = "mode select g0";
  1248.  
  1249.     return (scg_cmd(scgp));
  1250. }
  1251.  
  1252. EXPORT int
  1253. mode_select_g1(scgp, dp, cnt, smp, pf)
  1254.     SCSI    *scgp;
  1255.     Uchar    *dp;
  1256.     int    cnt;
  1257.     int    smp;
  1258.     int    pf;
  1259. {
  1260.     register struct    scg_cmd    *scmd = scgp->scmd;
  1261.  
  1262.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  1263.     scmd->addr = (caddr_t)dp;
  1264.     scmd->size = cnt;
  1265.     scmd->flags = SCG_DISRE_ENA;
  1266.     scmd->cdb_len = SC_G1_CDBLEN;
  1267.     scmd->sense_len = CCS_SENSE_LEN;
  1268.     scmd->target = scgp->target;
  1269.     scmd->cdb.g1_cdb.cmd = 0x55;
  1270.     scmd->cdb.g1_cdb.lun = scgp->lun;
  1271.     scmd->cdb.g0_cdb.high_addr = smp ? 1 : 0 | pf ? 0x10 : 0;
  1272.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  1273.  
  1274.     if (scgp->verbose) {
  1275.         printf("%s ", smp?"Save":"Set ");
  1276.         scg_prbytes("Mode Parameters", dp, cnt);
  1277.     }
  1278.  
  1279.     scgp->cmdname = "mode select g1";
  1280.  
  1281.     return (scg_cmd(scgp));
  1282. }
  1283.  
  1284. EXPORT int
  1285. mode_sense_g0(scgp, dp, cnt, page, pcf)
  1286.     SCSI    *scgp;
  1287.     Uchar    *dp;
  1288.     int    cnt;
  1289.     int    page;
  1290.     int    pcf;
  1291. {
  1292.     register struct    scg_cmd    *scmd = scgp->scmd;
  1293.  
  1294.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  1295.     scmd->addr = (caddr_t)dp;
  1296.     scmd->size = 0xFF;
  1297.     scmd->size = cnt;
  1298.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  1299.     scmd->cdb_len = SC_G0_CDBLEN;
  1300.     scmd->sense_len = CCS_SENSE_LEN;
  1301.     scmd->target = scgp->target;
  1302.     scmd->cdb.g0_cdb.cmd = SC_MODE_SENSE;
  1303.     scmd->cdb.g0_cdb.lun = scgp->lun;
  1304. #ifdef    nonono
  1305.     scmd->cdb.g0_cdb.high_addr = 1<<4;    /* DBD Disable Block desc. */
  1306. #endif
  1307.     scmd->cdb.g0_cdb.mid_addr = (page&0x3F) | ((pcf<<6)&0xC0);
  1308.     scmd->cdb.g0_cdb.count = page ? 0xFF : 24;
  1309.     scmd->cdb.g0_cdb.count = cnt;
  1310.  
  1311.     scgp->cmdname = "mode sense g0";
  1312.  
  1313.     if (scg_cmd(scgp) < 0)
  1314.         return (-1);
  1315.     if (scgp->verbose) scg_prbytes("Mode Sense Data", dp, cnt - scg_getresid(scgp));
  1316.     return (0);
  1317. }
  1318.  
  1319. EXPORT int
  1320. mode_sense_g1(scgp, dp, cnt, page, pcf)
  1321.     SCSI    *scgp;
  1322.     Uchar    *dp;
  1323.     int    cnt;
  1324.     int    page;
  1325.     int    pcf;
  1326. {
  1327.     register struct    scg_cmd    *scmd = scgp->scmd;
  1328.  
  1329.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  1330.     scmd->addr = (caddr_t)dp;
  1331.     scmd->size = cnt;
  1332.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  1333.     scmd->cdb_len = SC_G1_CDBLEN;
  1334.     scmd->sense_len = CCS_SENSE_LEN;
  1335.     scmd->target = scgp->target;
  1336.     scmd->cdb.g1_cdb.cmd = 0x5A;
  1337.     scmd->cdb.g1_cdb.lun = scgp->lun;
  1338. #ifdef    nonono
  1339.     scmd->cdb.g0_cdb.high_addr = 1<<4;    /* DBD Disable Block desc. */
  1340. #endif
  1341.     scmd->cdb.g1_cdb.addr[0] = (page&0x3F) | ((pcf<<6)&0xC0);
  1342.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  1343.  
  1344.     scgp->cmdname = "mode sense g1";
  1345.  
  1346.     if (scg_cmd(scgp) < 0)
  1347.         return (-1);
  1348.     if (scgp->verbose) scg_prbytes("Mode Sense Data", dp, cnt - scg_getresid(scgp));
  1349.     return (0);
  1350. }
  1351.  
  1352. struct tocheader {
  1353.     Uchar    len[2];
  1354.     Uchar    first;
  1355.     Uchar    last;
  1356. };
  1357.  
  1358. struct trackdesc {
  1359.     Uchar    res0;
  1360.  
  1361. #if defined(_BIT_FIELDS_LTOH)        /* Intel byteorder */
  1362.     Ucbit    control        : 4;
  1363.     Ucbit    adr        : 4;
  1364. #else                    /* Motorola byteorder */
  1365.     Ucbit    adr        : 4;
  1366.     Ucbit    control        : 4;
  1367. #endif
  1368.  
  1369.     Uchar    track;
  1370.     Uchar    res3;
  1371.     Uchar    addr[4];
  1372. };
  1373.  
  1374. struct diskinfo {
  1375.     struct tocheader    hd;
  1376.     struct trackdesc    desc[1];
  1377. };
  1378.  
  1379. struct siheader {
  1380.     Uchar    len[2];
  1381.     Uchar    finished;
  1382.     Uchar    unfinished;
  1383. };
  1384.  
  1385. struct sidesc {
  1386.     Uchar    sess_number;
  1387.     Uchar    res1;
  1388.     Uchar    track;
  1389.     Uchar    res3;
  1390.     Uchar    addr[4];
  1391. };
  1392.  
  1393. struct sinfo {
  1394.     struct siheader    hd;
  1395.     struct sidesc    desc[1];
  1396. };
  1397.  
  1398. struct trackheader {
  1399.     Uchar    mode;
  1400.     Uchar    res[3];
  1401.     Uchar    addr[4];
  1402. };
  1403. #define    TRM_ZERO    0
  1404. #define    TRM_USER_ECC    1    /* 2048 bytes user data + 288 Bytes ECC/EDC */
  1405. #define    TRM_USER    2    /* All user data (2336 bytes) */
  1406.  
  1407. struct ftrackdesc {
  1408.     Uchar    sess_number;
  1409.  
  1410. #if defined(_BIT_FIELDS_LTOH)        /* Intel byteorder */
  1411.     Ucbit    control        : 4;
  1412.     Ucbit    adr        : 4;
  1413. #else                    /* Motorola byteorder */
  1414.     Ucbit    adr        : 4;
  1415.     Ucbit    control        : 4;
  1416. #endif
  1417.  
  1418.     Uchar    track;
  1419.     Uchar    point;
  1420.     Uchar    amin;
  1421.     Uchar    asec;
  1422.     Uchar    aframe;
  1423.     Uchar    res7;
  1424.     Uchar    pmin;
  1425.     Uchar    psec;
  1426.     Uchar    pframe;
  1427. };
  1428.  
  1429. struct fdiskinfo {
  1430.     struct tocheader    hd;
  1431.     struct ftrackdesc    desc[1];
  1432. };
  1433.  
  1434.  
  1435. EXPORT    int
  1436. read_tochdr(scgp, dp, fp, lp)
  1437.     SCSI    *scgp;
  1438.     cdr_t    *dp;
  1439.     int    *fp;
  1440.     int    *lp;
  1441. {
  1442.     struct    tocheader *tp;
  1443.     char    xb[256];
  1444.     int    len;
  1445.  
  1446.     tp = (struct tocheader *)xb;
  1447.  
  1448.     fillbytes((caddr_t)xb, sizeof(xb), '\0');
  1449.     if (read_toc(scgp, xb, 0, sizeof(struct tocheader), 0, FMT_TOC) < 0) {
  1450.         if (scgp->silent == 0)
  1451.             errmsgno(EX_BAD, "Cannot read TOC header\n");
  1452.         return (-1);
  1453.     }
  1454.     len = a_to_u_2_byte(tp->len) + sizeof(struct tocheader)-2;
  1455.     if (len >= 4) {
  1456.         if (fp)
  1457.             *fp = tp->first;
  1458.         if (lp)
  1459.             *lp = tp->last;
  1460.         return (0);
  1461.     }
  1462.     return (-1);
  1463. }
  1464.     
  1465. EXPORT    int
  1466. read_cdtext(scgp)
  1467.     SCSI    *scgp;
  1468. {
  1469.     struct    tocheader *tp;
  1470.     char    xb[256];
  1471.     int    len;
  1472.     char    xxb[10000];
  1473.  
  1474.     tp = (struct tocheader *)xb;
  1475.  
  1476.     fillbytes((caddr_t)xb, sizeof(xb), '\0');
  1477.     if (read_toc(scgp, xb, 0, sizeof(struct tocheader), 0, FMT_CDTEXT) < 0) {
  1478.         if (scgp->silent == 0 || scgp->verbose > 0)
  1479.             errmsgno(EX_BAD, "Cannot read CD-Text header\n");
  1480.         return (-1);
  1481.     }
  1482.     len = a_to_u_2_byte(tp->len) + sizeof(struct tocheader)-2;
  1483.     printf("CD-Text len: %d\n", len);
  1484.  
  1485.     if (read_toc(scgp, xxb, 0, len, 0, FMT_CDTEXT) < 0) {
  1486.         if (scgp->silent == 0)
  1487.             errmsgno(EX_BAD, "Cannot read CD-Text\n");
  1488.         return (-1);
  1489.     }
  1490.     {
  1491.         FILE    *f = fileopen("cdtext.dat", "wct");
  1492.         filewrite(f, xxb, len);
  1493.     }
  1494.     return (0);
  1495. }
  1496.     
  1497. EXPORT    int
  1498. read_trackinfo(scgp, track, offp, msfp, adrp, controlp, modep)
  1499.     SCSI    *scgp;
  1500.     int    track;
  1501.     long    *offp;
  1502.     struct msf *msfp;
  1503.     int    *adrp;
  1504.     int    *controlp;
  1505.     int    *modep;
  1506. {
  1507.     struct    diskinfo *dp;
  1508.     char    xb[256];
  1509.     int    len;
  1510.  
  1511.     dp = (struct diskinfo *)xb;
  1512.  
  1513.     fillbytes((caddr_t)xb, sizeof(xb), '\0');
  1514.     if (read_toc(scgp, xb, track, sizeof(struct diskinfo), 0, FMT_TOC) < 0) {
  1515.         if (scgp->silent <= 0)
  1516.             errmsgno(EX_BAD, "Cannot read TOC\n");
  1517.         return (-1);
  1518.     }
  1519.     len = a_to_u_2_byte(dp->hd.len) + sizeof(struct tocheader)-2;
  1520.     if (len <  (int)sizeof(struct diskinfo))
  1521.         return (-1);
  1522.  
  1523.     if (offp)
  1524.         *offp = a_to_4_byte(dp->desc[0].addr);
  1525.     if (adrp)
  1526.         *adrp = dp->desc[0].adr;
  1527.     if (controlp)
  1528.         *controlp = dp->desc[0].control;
  1529.  
  1530.     if (msfp) {
  1531.         scgp->silent++;
  1532.         if (read_toc(scgp, xb, track, sizeof(struct diskinfo), 1, FMT_TOC)
  1533.                                     >= 0) {
  1534.             msfp->msf_min = dp->desc[0].addr[1];
  1535.             msfp->msf_sec = dp->desc[0].addr[2];
  1536.             msfp->msf_frame = dp->desc[0].addr[3];
  1537.         } else if (read_toc(scgp, xb, track, sizeof(struct diskinfo), 0, FMT_TOC)
  1538.                                     >= 0) {
  1539.             /*
  1540.              * Some drives (e.g. the Philips CDD-522) don't support
  1541.              * to read the TOC in MSF mode.
  1542.              */
  1543.             long off = a_to_4_byte(dp->desc[0].addr);
  1544.  
  1545.             lba_to_msf(off, msfp);
  1546.         } else {
  1547.             msfp->msf_min = 0;
  1548.             msfp->msf_sec = 0;
  1549.             msfp->msf_frame = 0;
  1550.         }
  1551.         scgp->silent--;
  1552.     }
  1553.  
  1554.     if (modep == NULL)
  1555.         return (0);
  1556.  
  1557.     if (track == 0xAA) {
  1558.         *modep = -1;
  1559.         return (0);
  1560.     }
  1561.  
  1562.     fillbytes((caddr_t)xb, sizeof(xb), '\0');
  1563.  
  1564.     scgp->silent++;
  1565.     if (read_header(scgp, xb, *offp, 8, 0) >= 0) {
  1566.         *modep = xb[0];
  1567.     } else if (read_track_info_philips(scgp, xb, track, 14) >= 0) {
  1568.         *modep = xb[0xb] & 0xF;
  1569.     } else {
  1570.         *modep = -1;
  1571.     }
  1572.     scgp->silent--;
  1573.     return (0);
  1574. }
  1575.  
  1576. EXPORT    int
  1577. read_B0(scgp, isbcd, b0p, lop)
  1578.     SCSI    *scgp;
  1579.     BOOL    isbcd;
  1580.     long    *b0p;
  1581.     long    *lop;
  1582. {
  1583.     struct    fdiskinfo *dp;
  1584.     struct    ftrackdesc *tp;
  1585.     char    xb[8192];
  1586.     char    *pe;
  1587.     int    len;
  1588.     long    l;
  1589.  
  1590.     dp = (struct fdiskinfo *)xb;
  1591.  
  1592.     fillbytes((caddr_t)xb, sizeof(xb), '\0');
  1593.     if (read_toc_philips(scgp, xb, 1, sizeof(struct tocheader), 0, FMT_FULLTOC) < 0) {
  1594.         return (-1);
  1595.     }
  1596.     len = a_to_u_2_byte(dp->hd.len) + sizeof(struct tocheader)-2;
  1597.     if (len <  (int)sizeof(struct fdiskinfo))
  1598.         return (-1);
  1599.     if (read_toc_philips(scgp, xb, 1, len, 0, FMT_FULLTOC) < 0) {
  1600.         return (-1);
  1601.     }
  1602.     if (scgp->verbose) {
  1603.         scg_prbytes("TOC data: ", (Uchar *)xb,
  1604.             len > (int)sizeof(xb) - scg_getresid(scgp) ?
  1605.                 sizeof(xb) - scg_getresid(scgp) : len);
  1606.  
  1607.         tp = &dp->desc[0];
  1608.         pe = &xb[len];
  1609.  
  1610.         while ((char *)tp < pe) {
  1611.             scg_prbytes("ENT: ", (Uchar *)tp, 11);
  1612.             tp++;
  1613.         }
  1614.     }
  1615.     tp = &dp->desc[0];
  1616.     pe = &xb[len];
  1617.  
  1618.     for (; (char *)tp < pe; tp++) {
  1619.         if (tp->sess_number != dp->hd.last)
  1620.             continue;
  1621.         if (tp->point != 0xB0)
  1622.             continue;
  1623.         if (scgp->verbose)
  1624.             scg_prbytes("B0: ", (Uchar *)tp, 11);
  1625.         if (isbcd) {
  1626.             l = msf_to_lba(from_bcd(tp->amin),
  1627.                 from_bcd(tp->asec),
  1628.                 from_bcd(tp->aframe), TRUE);
  1629.         } else {
  1630.             l = msf_to_lba(tp->amin,
  1631.                 tp->asec,
  1632.                 tp->aframe, TRUE);
  1633.         }
  1634.         if (b0p)
  1635.             *b0p = l;
  1636.  
  1637.         if (scgp->verbose)
  1638.             printf("B0 start: %ld\n", l);
  1639.  
  1640.         if (isbcd) {
  1641.             l = msf_to_lba(from_bcd(tp->pmin),
  1642.                 from_bcd(tp->psec),
  1643.                 from_bcd(tp->pframe), TRUE);
  1644.         } else {
  1645.             l = msf_to_lba(tp->pmin,
  1646.                 tp->psec,
  1647.                 tp->pframe, TRUE);
  1648.         }
  1649.  
  1650.         if (scgp->verbose)
  1651.             printf("B0 lout: %ld\n", l);
  1652.         if (lop)
  1653.             *lop = l;
  1654.         return (0);
  1655.     }
  1656.     return (-1);
  1657. }
  1658.  
  1659.  
  1660. /*
  1661.  * Return address of first track in last session (SCSI-3/mmc version).
  1662.  */
  1663. EXPORT int
  1664. read_session_offset(scgp, offp)
  1665.     SCSI    *scgp;
  1666.     long    *offp;
  1667. {
  1668.     struct    diskinfo *dp;
  1669.     char    xb[256];
  1670.     int    len;
  1671.  
  1672.     dp = (struct diskinfo *)xb;
  1673.  
  1674.     fillbytes((caddr_t)xb, sizeof(xb), '\0');
  1675.     if (read_toc(scgp, (caddr_t)xb, 0, sizeof(struct tocheader), 0, FMT_SINFO) < 0)
  1676.         return (-1);
  1677.  
  1678.     if (scgp->verbose)
  1679.         scg_prbytes("tocheader: ",
  1680.         (Uchar *)xb, sizeof(struct tocheader) - scg_getresid(scgp));
  1681.  
  1682.     len = a_to_u_2_byte(dp->hd.len) + sizeof(struct tocheader)-2;
  1683.     if (len > (int)sizeof(xb)) {
  1684.         errmsgno(EX_BAD, "Session info too big.\n");
  1685.         return (-1);
  1686.     }
  1687.     if (read_toc(scgp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0)
  1688.         return (-1);
  1689.  
  1690.     if (scgp->verbose)
  1691.         scg_prbytes("tocheader: ",
  1692.             (Uchar *)xb, len - scg_getresid(scgp));
  1693.  
  1694.     dp = (struct diskinfo *)xb;
  1695.     if (offp)
  1696.         *offp = a_to_u_4_byte(dp->desc[0].addr);
  1697.     return (0);
  1698. }
  1699.  
  1700. /*
  1701.  * Return address of first track in last session (pre SCSI-3 version).
  1702.  */
  1703. EXPORT int
  1704. read_session_offset_philips(scgp, offp)
  1705.     SCSI    *scgp;
  1706.     long    *offp;
  1707. {
  1708.     struct    sinfo *sp;
  1709.     char    xb[256];
  1710.     int    len;
  1711.  
  1712.     sp = (struct sinfo *)xb;
  1713.  
  1714.     fillbytes((caddr_t)xb, sizeof(xb), '\0');
  1715.     if (read_toc_philips(scgp, (caddr_t)xb, 0, sizeof(struct siheader), 0, FMT_SINFO) < 0)
  1716.         return (-1);
  1717.     len = a_to_u_2_byte(sp->hd.len) + sizeof(struct siheader)-2;
  1718.     if (len > (int)sizeof(xb)) {
  1719.         errmsgno(EX_BAD, "Session info too big.\n");
  1720.         return (-1);
  1721.     }
  1722.     if (read_toc_philips(scgp, (caddr_t)xb, 0, len, 0, FMT_SINFO) < 0)
  1723.         return (-1);
  1724.     /*
  1725.      * Old drives return the number of finished sessions in first/finished
  1726.      * a descriptor is returned for each session. 
  1727.      * New drives return the number of the first and last session
  1728.      * one descriptor for the last finished session is returned
  1729.      * as in SCSI-3
  1730.      * In all cases the lowest session number is set to 1.
  1731.      */
  1732.     sp = (struct sinfo *)xb;
  1733.     if (offp)
  1734.         *offp = a_to_u_4_byte(sp->desc[sp->hd.finished-1].addr);
  1735.     return (0);
  1736. }
  1737.  
  1738. EXPORT int
  1739. sense_secsize(scgp, current)
  1740.     SCSI    *scgp;
  1741.     int    current;
  1742. {
  1743.     Uchar    mode[0x100];
  1744.     Uchar    *p;
  1745.     Uchar    *ep;
  1746.     int    secsize = -1;
  1747.  
  1748.     scgp->silent++;
  1749.     (void)unit_ready(scgp);
  1750.     scgp->silent--;
  1751.  
  1752.     /* XXX Quick and dirty, musz verallgemeinert werden !!! */
  1753.  
  1754.     fillbytes(mode, sizeof(mode), '\0');
  1755.     scgp->silent++;
  1756.     if (mode_sense(scgp, mode, 0xFF, 0x3F, current?0:2) < 0) {    /* All Pages */
  1757.         fillbytes(mode, sizeof(mode), '\0');
  1758.         if (mode_sense(scgp, mode, 0xFF, 0, current?0:2) < 0)    {/* VU (block desc) */
  1759.             scgp->silent--;
  1760.             return (-1);
  1761.         }
  1762.     }
  1763.     scgp->silent--;
  1764.  
  1765.     ep = mode+mode[0];    /* Points to last byte of data */
  1766.     p = &mode[4];
  1767.     p += mode[3];
  1768.     if (scgp->debug) {
  1769.         printf("Pages: ");
  1770.         while (p < ep) {
  1771.             printf("0x%x ", *p&0x3F);
  1772.             p += p[1]+2;
  1773.         }
  1774.         printf("\n");
  1775.     }
  1776.  
  1777.     if (mode[3] == 8) {
  1778.         if (scgp->debug) {
  1779.             printf("Density: 0x%x\n", mode[4]);
  1780.             printf("Blocks:  %ld\n", a_to_u_3_byte(&mode[5]));
  1781.             printf("Blocklen:%ld\n", a_to_u_3_byte(&mode[9]));
  1782.         }
  1783.         secsize = a_to_u_3_byte(&mode[9]);
  1784.     }
  1785.     return (secsize);
  1786. }
  1787.  
  1788. EXPORT int
  1789. select_secsize(scgp, secsize)
  1790.     SCSI    *scgp;
  1791.     int    secsize;
  1792. {
  1793.     struct scsi_mode_data md;
  1794.     int    count = sizeof(struct scsi_mode_header) +
  1795.             sizeof(struct scsi_mode_blockdesc);
  1796.  
  1797.     (void)test_unit_ready(scgp);    /* clear any error situation */
  1798.  
  1799.     fillbytes((caddr_t)&md, sizeof(md), '\0');
  1800.     md.header.blockdesc_len = 8;
  1801.     i_to_3_byte(md.blockdesc.lblen, secsize);
  1802.     
  1803.     return (mode_select(scgp, (Uchar *)&md, count, 0, scgp->inq->data_format >= 2));
  1804. }
  1805.  
  1806. EXPORT BOOL
  1807. is_cddrive(scgp)
  1808.     SCSI    *scgp;
  1809. {
  1810.     return (scgp->inq->type == INQ_ROMD || scgp->inq->type == INQ_WORM);
  1811. }
  1812.  
  1813. EXPORT BOOL
  1814. is_unknown_dev(scgp)
  1815.     SCSI    *scgp;
  1816. {
  1817.     return (scgp->dev == DEV_UNKNOWN);
  1818. }
  1819.  
  1820. #define    DEBUG
  1821. #ifdef    DEBUG
  1822. #define    G0_MAXADDR    0x1FFFFFL
  1823.  
  1824. EXPORT int
  1825. read_scsi(scgp, bp, addr, cnt)
  1826.     SCSI    *scgp;
  1827.     caddr_t    bp;
  1828.     long    addr;
  1829.     int    cnt;
  1830. {
  1831.     if(addr <= G0_MAXADDR && cnt < 256 && !is_atapi)
  1832.         return (read_g0(scgp, bp, addr, cnt));
  1833.     else
  1834.         return (read_g1(scgp, bp, addr, cnt));
  1835. }
  1836.  
  1837. EXPORT int
  1838. read_g0(scgp, bp, addr, cnt)
  1839.     SCSI    *scgp;
  1840.     caddr_t    bp;
  1841.     long    addr;
  1842.     int    cnt;
  1843. {
  1844.     register struct    scg_cmd    *scmd = scgp->scmd;
  1845.  
  1846.     if (scgp->cap->c_bsize <= 0)
  1847.         raisecond("capacity_not_set", 0L);
  1848.  
  1849.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  1850.     scmd->addr = bp;
  1851.     scmd->size = cnt*scgp->cap->c_bsize;
  1852.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  1853.     scmd->cdb_len = SC_G0_CDBLEN;
  1854.     scmd->sense_len = CCS_SENSE_LEN;
  1855.     scmd->target = scgp->target;
  1856.     scmd->cdb.g0_cdb.cmd = SC_READ;
  1857.     scmd->cdb.g0_cdb.lun = scgp->lun;
  1858.     g0_cdbaddr(&scmd->cdb.g0_cdb, addr);
  1859.     scmd->cdb.g0_cdb.count = cnt;
  1860. /*    scmd->cdb.g0_cdb.vu_56 = 1;*/
  1861.     
  1862.     scgp->cmdname = "read_g0";
  1863.  
  1864.     return (scg_cmd(scgp));
  1865. }
  1866.  
  1867. EXPORT int
  1868. read_g1(scgp, bp, addr, cnt)
  1869.     SCSI    *scgp;
  1870.     caddr_t    bp;
  1871.     long    addr;
  1872.     int    cnt;
  1873. {
  1874.     register struct    scg_cmd    *scmd = scgp->scmd;
  1875.  
  1876.     if (scgp->cap->c_bsize <= 0)
  1877.         raisecond("capacity_not_set", 0L);
  1878.  
  1879.     fillbytes((caddr_t)scmd, sizeof(*scmd), '\0');
  1880.     scmd->addr = bp;
  1881.     scmd->size = cnt*scgp->cap->c_bsize;
  1882.     scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
  1883.     scmd->cdb_len = SC_G1_CDBLEN;
  1884.     scmd->sense_len = CCS_SENSE_LEN;
  1885.     scmd->target = scgp->target;
  1886.     scmd->cdb.g1_cdb.cmd = SC_EREAD;
  1887.     scmd->cdb.g1_cdb.lun = scgp->lun;
  1888.     g1_cdbaddr(&scmd->cdb.g1_cdb, addr);
  1889.     g1_cdblen(&scmd->cdb.g1_cdb, cnt);
  1890.     
  1891.     scgp->cmdname = "read_g1";
  1892.  
  1893.     return (scg_cmd(scgp));
  1894. }
  1895. #endif    /* DEBUG */
  1896.  
  1897. EXPORT BOOL
  1898. getdev(scgp, print)
  1899.     SCSI    *scgp;
  1900.     BOOL    print;
  1901. {
  1902.          BOOL    got_inquiry = TRUE;
  1903.          char    vendor_info[8+1];
  1904.          char    prod_ident[16+1];
  1905.          char    prod_revision[4+1];
  1906.          int    inq_len = 0;
  1907.     register struct    scg_cmd    *scmd = scgp->scmd;
  1908.     register struct scsi_inquiry *inq = scgp->inq;
  1909.  
  1910.  
  1911.     fillbytes((caddr_t)inq, sizeof(*inq), '\0');
  1912.     scgp->dev = DEV_UNKNOWN;
  1913.     scgp->silent++;
  1914.     (void)unit_ready(scgp);
  1915.     if (scmd->error >= SCG_FATAL &&
  1916.                 !(scmd->scb.chk && scmd->sense_count > 0)) {
  1917.         scgp->silent--;
  1918.         return (FALSE);
  1919.     }
  1920.  
  1921.  
  1922. /*    if (scmd->error < SCG_FATAL || scmd->scb.chk && scmd->sense_count > 0){*/
  1923.  
  1924.     if (inquiry(scgp, (caddr_t)inq, sizeof(*inq)) < 0) {
  1925.         got_inquiry = FALSE;
  1926.     } else {
  1927.         inq_len = sizeof(*inq) - scg_getresid(scgp);
  1928.     }
  1929.     if (!got_inquiry) {
  1930.         if (scgp->verbose) {
  1931.             printf(
  1932.         "error: %d scb.chk: %d sense_count: %d sense.code: 0x%x\n",
  1933.                 scmd->error, scmd->scb.chk,
  1934.                 scmd->sense_count, scmd->sense.code);
  1935.         }
  1936.             /*
  1937.              * Folgende Kontroller kennen das Kommando
  1938.              * INQUIRY nicht:
  1939.              *
  1940.              * ADAPTEC    ACB-4000, ACB-4010, ACB 4070
  1941.              * SYSGEN    SC4000
  1942.              *
  1943.              * Leider reagieren ACB40X0 und ACB5500 identisch
  1944.              * wenn drive not ready (code == not ready),
  1945.              * sie sind dann nicht zu unterscheiden.
  1946.              */
  1947.  
  1948.         if (scmd->scb.chk && scmd->sense_count == 4) {
  1949.             /* Test auf SYSGEN                 */
  1950.             (void)qic02(scgp, 0x12);    /* soft lock on  */
  1951.             if (qic02(scgp, 1) < 0) {    /* soft lock off */
  1952.                 scgp->dev = DEV_ACB40X0;
  1953. /*                scgp->dev = acbdev();*/
  1954.             } else {
  1955.                 scgp->dev = DEV_SC4000;
  1956.                 inq->type = INQ_SEQD;
  1957.                 inq->removable = 1;
  1958.             }
  1959.         }
  1960.     } else if (scgp->verbose) {
  1961.         int    i;
  1962.         int    len = inq->add_len + 5;
  1963.         Uchar    ibuf[256+5];
  1964.         Uchar    *ip = (Uchar *)inq;
  1965.         Uchar    c;
  1966.  
  1967.         if (len > (int)sizeof (*inq) &&
  1968.                 inquiry(scgp, (caddr_t)ibuf, inq->add_len+5) >= 0) {
  1969.             len = inq->add_len+5 - scg_getresid(scgp);
  1970.             ip = ibuf;
  1971.         } else {
  1972.             len = sizeof (*inq);
  1973.         }
  1974.         printf("Inquiry Data   : ");
  1975.         for (i = 0; i < len; i++) {
  1976.             c = ip[i];
  1977.             if (c >= ' ' && c < 0177)
  1978.                 printf("%c", c);
  1979.             else
  1980.                 printf(".");
  1981.         }
  1982.         printf("\n");
  1983.     }
  1984.  
  1985.     strncpy(vendor_info, inq->vendor_info, sizeof(inq->vendor_info));
  1986.     strncpy(prod_ident, inq->prod_ident, sizeof(inq->prod_ident));
  1987.     strncpy(prod_revision, inq->prod_revision, sizeof(inq->prod_revision));
  1988.  
  1989.     vendor_info[sizeof(inq->vendor_info)] = '\0';
  1990.     prod_ident[sizeof(inq->prod_ident)] = '\0';
  1991.     prod_revision[sizeof(inq->prod_revision)] = '\0';
  1992.  
  1993.     switch (inq->type) {
  1994.  
  1995.     case INQ_DASD:
  1996.         if (inq->add_len == 0 && inq->vendor_info[0] != '\0') {
  1997.             Uchar    *p;
  1998.             /*
  1999.              * NT-4.0 creates fake inquiry data for IDE disks.
  2000.              * Unfortunately, it does not set add_len wo we
  2001.              * check if vendor_info, prod_ident and prod_revision
  2002.              * contains valid chars for a CCS inquiry.
  2003.              */
  2004.             if (inq_len >= 36)
  2005.                 inq->add_len = 31;
  2006.  
  2007.             for (p = (Uchar *)&inq->vendor_info[0];
  2008.                     p < (Uchar *)&inq->prod_revision[4];
  2009.                                     p++) {
  2010.                 if (*p < 0x20 || *p > 0x7E) {
  2011.                     inq->add_len = 0;
  2012.                     break;
  2013.                 }
  2014.             }
  2015.         }
  2016.         if (inq->add_len == 0) {
  2017.             if (scgp->dev == DEV_UNKNOWN && got_inquiry) {
  2018.                 scgp->dev = DEV_ACB5500;
  2019.                 strcpy(inq->vendor_info,
  2020.                     "ADAPTEC ACB-5500        FAKE");
  2021.  
  2022.             } else switch (scgp->dev) {
  2023.  
  2024.             case DEV_ACB40X0:
  2025.                 strcpy(inq->vendor_info,
  2026.                     "ADAPTEC ACB-40X0        FAKE");
  2027.                 break;
  2028.             case DEV_ACB4000:
  2029.                 strcpy(inq->vendor_info,
  2030.                     "ADAPTEC ACB-4000        FAKE");
  2031.                 break;
  2032.             case DEV_ACB4010:
  2033.                 strcpy(inq->vendor_info,
  2034.                     "ADAPTEC ACB-4010        FAKE");
  2035.                 break;
  2036.             case DEV_ACB4070:
  2037.                 strcpy(inq->vendor_info,
  2038.                     "ADAPTEC ACB-4070        FAKE");
  2039.                 break;
  2040.             }
  2041.         } else if (inq->add_len < 31) {
  2042.             scgp->dev = DEV_NON_CCS_DSK;
  2043.  
  2044.         } else if (strbeg("EMULEX", vendor_info)) {
  2045.             if (strbeg("MD21", prod_ident))
  2046.                 scgp->dev = DEV_MD21;
  2047.             if (strbeg("MD23", prod_ident))
  2048.                 scgp->dev = DEV_MD23;
  2049.             else
  2050.                 scgp->dev = DEV_CCS_GENDISK;
  2051.         } else if (strbeg("ADAPTEC", vendor_info)) {
  2052.             if (strbeg("ACB-4520", prod_ident))
  2053.                 scgp->dev = DEV_ACB4520A;
  2054.             if (strbeg("ACB-4525", prod_ident))
  2055.                 scgp->dev = DEV_ACB4525;
  2056.             else
  2057.                 scgp->dev = DEV_CCS_GENDISK;
  2058.         } else if (strbeg("SONY", vendor_info) &&
  2059.                     strbeg("SMO-C501", prod_ident)) {
  2060.             scgp->dev = DEV_SONY_SMO;
  2061.         } else {
  2062.             scgp->dev = DEV_CCS_GENDISK;
  2063.         }
  2064.         break;
  2065.  
  2066.     case INQ_SEQD:
  2067.         if (scgp->dev == DEV_SC4000) {
  2068.             strcpy(inq->vendor_info,
  2069.                 "SYSGEN  SC4000          FAKE");
  2070.         } else if (inq->add_len == 0 &&
  2071.                     inq->removable &&
  2072.                         inq->ansi_version == 1) {
  2073.             scgp->dev = DEV_MT02;
  2074.             strcpy(inq->vendor_info,
  2075.                 "EMULEX  MT02            FAKE");
  2076.         }
  2077.         break;
  2078.  
  2079. /*    case INQ_OPTD:*/
  2080.     case INQ_ROMD:
  2081.     case INQ_WORM:
  2082.         if (strbeg("RXT-800S", prod_ident))
  2083.             scgp->dev = DEV_RXT800S;
  2084.  
  2085.         /*
  2086.          * Start of CD-Recorders:
  2087.          */
  2088.         if (strbeg("ACER", vendor_info)) { 
  2089.             if (strbeg("CR-4020C", prod_ident)) 
  2090.                                 scgp->dev = DEV_RICOH_RO_1420C;
  2091.  
  2092.         } else if (strbeg("CREATIVE", vendor_info)) { 
  2093.             if (strbeg("CDR2000", prod_ident))
  2094.                 scgp->dev = DEV_RICOH_RO_1060C;
  2095.  
  2096.         } else if (strbeg("GRUNDIG", vendor_info)) { 
  2097.             if (strbeg("CDR100IPW", prod_ident))
  2098.                 scgp->dev = DEV_CDD_2000;
  2099.  
  2100.         } else if (strbeg("JVC", vendor_info)) {
  2101.             if (strbeg("XR-W2001", prod_ident))
  2102.                 scgp->dev = DEV_TEAC_CD_R50S;
  2103.             else if (strbeg("XR-W2010", prod_ident))
  2104.                 scgp->dev = DEV_TEAC_CD_R50S;
  2105.             else if (strbeg("R2626", prod_ident))
  2106.                 scgp->dev = DEV_TEAC_CD_R50S;
  2107.  
  2108.         } else if (strbeg("MITSBISH", vendor_info)) {
  2109.  
  2110. #ifdef    XXXX_REALLY
  2111.             /* It's MMC compliant */
  2112.             if (strbeg("CDRW226", prod_ident))
  2113.                 scgp->dev = DEV_MMC_CDRW;
  2114. #endif
  2115.  
  2116.         } else if (strbeg("MITSUMI", vendor_info)) {
  2117.             /* Don't know any product string */
  2118.             scgp->dev = DEV_CDD_522;
  2119.  
  2120.         } else if (strbeg("OPTIMA", vendor_info)) {
  2121.             if (strbeg("CD-R 650", prod_ident))
  2122.                 scgp->dev = DEV_SONY_CDU_924;
  2123.  
  2124.         } else if (strbeg("PHILIPS", vendor_info) ||
  2125.                 strbeg("IMS", vendor_info) ||
  2126.                 strbeg("KODAK", vendor_info) ||
  2127.                 strbeg("HP", vendor_info)) {
  2128.  
  2129.             if (strbeg("CDD521/00", prod_ident))
  2130.                 scgp->dev = DEV_CDD_521_OLD;
  2131.             else if (strbeg("CDD521/02", prod_ident))
  2132.                 scgp->dev = DEV_CDD_521_OLD;        /* PCD 200R? */
  2133.             else if (strbeg("CDD521", prod_ident))
  2134.                 scgp->dev = DEV_CDD_521;
  2135.  
  2136.             if (strbeg("CDD522", prod_ident))
  2137.                 scgp->dev = DEV_CDD_522;
  2138.             if (strbeg("PCD225", prod_ident))
  2139.                 scgp->dev = DEV_CDD_522;
  2140.             if (strbeg("KHSW/OB", prod_ident))    /* PCD600 */
  2141.                 scgp->dev = DEV_PCD_600;
  2142.             if (strbeg("CDR-240", prod_ident))
  2143.                 scgp->dev = DEV_CDD_2000;
  2144.  
  2145.             if (strbeg("CDD20", prod_ident))
  2146.                 scgp->dev = DEV_CDD_2000;
  2147.             if (strbeg("CDD26", prod_ident))
  2148.                 scgp->dev = DEV_CDD_2600;
  2149.  
  2150.             if (strbeg("C4324/C4325", prod_ident))
  2151.                 scgp->dev = DEV_CDD_2000;
  2152.             if (strbeg("CD-Writer 6020", prod_ident))
  2153.                 scgp->dev = DEV_CDD_2600;
  2154.  
  2155.         } else if (strbeg("PINNACLE", vendor_info)) {
  2156.             if (strbeg("RCD-1000", prod_ident))
  2157.                 scgp->dev = DEV_TEAC_CD_R50S;
  2158.             if (strbeg("RCD5020", prod_ident))
  2159.                 scgp->dev = DEV_TEAC_CD_R50S;
  2160.             if (strbeg("RCD5040", prod_ident))
  2161.                 scgp->dev = DEV_TEAC_CD_R50S;
  2162.             if (strbeg("RCD 4X4", prod_ident))
  2163.                 scgp->dev = DEV_TEAC_CD_R50S;
  2164.  
  2165.         } else if (strbeg("PIONEER", vendor_info)) {
  2166.             if (strbeg("CD-WO DW-S114X", prod_ident))
  2167.                 scgp->dev = DEV_PIONEER_DW_S114X;
  2168.             else if (strbeg("DVD-R DVR-S101", prod_ident))
  2169.                 scgp->dev = DEV_PIONEER_DVDR_S101;
  2170.  
  2171.         } else if (strbeg("PLASMON", vendor_info)) {
  2172.             if (strbeg("RF4100", prod_ident))
  2173.                 scgp->dev = DEV_PLASMON_RF_4100;
  2174.             else if (strbeg("CDR4220", prod_ident))
  2175.                 scgp->dev = DEV_CDD_2000;
  2176.  
  2177.         } else if (strbeg("PLEXTOR", vendor_info)) {
  2178.             if (strbeg("CD-R   PX-R24CS", prod_ident))
  2179.                 scgp->dev = DEV_RICOH_RO_1420C;
  2180.  
  2181.         } else if (strbeg("RICOH", vendor_info)) {
  2182.             if (strbeg("RO-1420C", prod_ident))
  2183.                 scgp->dev = DEV_RICOH_RO_1420C;
  2184.             if (strbeg("RO1060C", prod_ident))
  2185.                 scgp->dev = DEV_RICOH_RO_1060C;
  2186.  
  2187.         } else if (strbeg("SAF", vendor_info)) {    /* Smart & Friendly */
  2188.             if (strbeg("CD-R2004", prod_ident) ||
  2189.                 strbeg("CD-R2006 ", prod_ident))
  2190.                 scgp->dev = DEV_SONY_CDU_924;
  2191.             else if (strbeg("CD-R2006PLUS", prod_ident))
  2192.                 scgp->dev = DEV_TEAC_CD_R50S;
  2193.             else if (strbeg("CD-RW226", prod_ident))
  2194.                 scgp->dev = DEV_TEAC_CD_R50S;
  2195.             else if (strbeg("CD-R4012", prod_ident))
  2196.                 scgp->dev = DEV_TEAC_CD_R50S;
  2197.  
  2198.         } else if (strbeg("SANYO", vendor_info)) {
  2199.             if (strbeg("CD-WO CRD-R24S", prod_ident))
  2200.                 scgp->dev = DEV_CDD_521;
  2201.  
  2202.         } else if (strbeg("SONY", vendor_info)) {
  2203.             if (strbeg("CD-R   CDU92", prod_ident) ||
  2204.                 strbeg("CD-R   CDU94", prod_ident))
  2205.                 scgp->dev = DEV_SONY_CDU_924;
  2206.  
  2207.         } else if (strbeg("TEAC", vendor_info)) {
  2208.             if (strbeg("CD-R50S", prod_ident) ||
  2209.                 strbeg("CD-R55S", prod_ident))
  2210.                 scgp->dev = DEV_TEAC_CD_R50S;
  2211.  
  2212.         } else if (strbeg("TRAXDATA", vendor_info) ||
  2213.                 strbeg("Traxdata", vendor_info)) {
  2214.             if (strbeg("CDR4120", prod_ident))
  2215.                 scgp->dev = DEV_TEAC_CD_R50S;
  2216.  
  2217.         } else if (strbeg("T.YUDEN", vendor_info)) {
  2218.             if (strbeg("CD-WO EW-50", prod_ident))
  2219.                 scgp->dev = DEV_CDD_521;
  2220.  
  2221.         } else if (strbeg("WPI", vendor_info)) {    /* Wearnes */
  2222.             if (strbeg("CDR-632P", prod_ident))
  2223.                 scgp->dev = DEV_CDD_2600;
  2224.  
  2225.         } else if (strbeg("YAMAHA", vendor_info)) {
  2226.             if (strbeg("CDR10", prod_ident))
  2227.                 scgp->dev = DEV_YAMAHA_CDR_100;
  2228.             if (strbeg("CDR200", prod_ident))
  2229.                 scgp->dev = DEV_YAMAHA_CDR_400;
  2230.             if (strbeg("CDR400", prod_ident))
  2231.                 scgp->dev = DEV_YAMAHA_CDR_400;
  2232.  
  2233.         } else if (strbeg("MATSHITA", vendor_info)) {
  2234.             if (strbeg("CD-R   CW-7501", prod_ident))
  2235.                 scgp->dev = DEV_MATSUSHITA_7501;
  2236.             if (strbeg("CD-R   CW-7502", prod_ident))
  2237.                 scgp->dev = DEV_MATSUSHITA_7502;
  2238.         }
  2239.         if (scgp->dev == DEV_UNKNOWN) {
  2240.             /*
  2241.              * We do not have Manufacturer strings for
  2242.              * the following drives.
  2243.              */
  2244.             if (strbeg("CDS615E", prod_ident))    /* Olympus */
  2245.                 scgp->dev = DEV_SONY_CDU_924;
  2246.         }
  2247.         if (scgp->dev == DEV_UNKNOWN && inq->type == INQ_ROMD) {
  2248.             BOOL    cdrr     = FALSE;
  2249.             BOOL    cdwr     = FALSE;
  2250.             BOOL    cdrrw     = FALSE;
  2251.             BOOL    cdwrw     = FALSE;
  2252.             BOOL    dvd     = FALSE;
  2253.  
  2254.             scgp->dev = DEV_CDROM;
  2255.  
  2256.             if (mmc_check(scgp, &cdrr, &cdwr, &cdrrw, &cdwrw, &dvd))
  2257.                 scgp->dev = DEV_MMC_CDROM;
  2258.             if (cdwr)
  2259.                 scgp->dev = DEV_MMC_CDR;
  2260.             if (cdwrw)
  2261.                 scgp->dev = DEV_MMC_CDRW;
  2262.             if (dvd)
  2263.                 scgp->dev = DEV_MMC_DVD;
  2264.         }
  2265.  
  2266.     case INQ_PROCD:
  2267.         if (strbeg("BERTHOLD", vendor_info)) {
  2268.             if (strbeg("", prod_ident))
  2269.                 scgp->dev = DEV_HRSCAN;
  2270.         }
  2271.         break;
  2272.  
  2273.     case INQ_SCAN:
  2274.         scgp->dev = DEV_MS300A;
  2275.         break;
  2276.     }
  2277.     scgp->silent--;
  2278.     if (!print)
  2279.         return (TRUE);
  2280.  
  2281.     if (scgp->dev == DEV_UNKNOWN && !got_inquiry) {
  2282. #ifdef    PRINT_INQ_ERR
  2283.         scg_printerr(scgp);
  2284. #endif
  2285.         return (FALSE);
  2286.     }
  2287.  
  2288.     printf("Device type    : ");
  2289.     scg_printdev(inq);
  2290.     printf("Version        : %d\n", inq->ansi_version);
  2291.     printf("Response Format: %d\n", inq->data_format);
  2292.     if (inq->data_format >= 2) {
  2293.         printf("Capabilities   : ");
  2294.         if (inq->aenc)        printf("AENC ");
  2295.         if (inq->termiop)    printf("TERMIOP ");
  2296.         if (inq->reladr)    printf("RELADR ");
  2297.         if (inq->wbus32)    printf("WBUS32 ");
  2298.         if (inq->wbus16)    printf("WBUS16 ");
  2299.         if (inq->sync)        printf("SYNC ");
  2300.         if (inq->linked)    printf("LINKED ");
  2301.         if (inq->cmdque)    printf("CMDQUE ");
  2302.         if (inq->softreset)    printf("SOFTRESET ");
  2303.         printf("\n");
  2304.     }
  2305.     if (inq->add_len >= 31 ||
  2306.             inq->info[0] || inq->ident[0] || inq->revision[0]) {
  2307.         printf("Vendor_info    : '%.8s'\n", inq->info);
  2308.         printf("Identifikation : '%.16s'\n", inq->ident);
  2309.         printf("Revision       : '%.4s'\n", inq->revision);
  2310.     }
  2311.     return (TRUE);
  2312. }
  2313.  
  2314. EXPORT void
  2315. printdev(scgp)
  2316.     SCSI    *scgp;
  2317. {
  2318.     printf("Device seems to be: ");
  2319.  
  2320.     switch (scgp->dev) {
  2321.  
  2322.     case DEV_UNKNOWN:    printf("unknown");        break;
  2323.     case DEV_ACB40X0:    printf("Adaptec 4000/4010/4070");break;
  2324.     case DEV_ACB4000:    printf("Adaptec 4000");        break;
  2325.     case DEV_ACB4010:    printf("Adaptec 4010");        break;
  2326.     case DEV_ACB4070:    printf("Adaptec 4070");        break;
  2327.     case DEV_ACB5500:    printf("Adaptec 5500");        break;
  2328.     case DEV_ACB4520A:    printf("Adaptec 4520A");    break;
  2329.     case DEV_ACB4525:    printf("Adaptec 4525");        break;
  2330.     case DEV_MD21:        printf("Emulex MD21");        break;
  2331.     case DEV_MD23:        printf("Emulex MD23");        break;
  2332.     case DEV_NON_CCS_DSK:    printf("Generic NON CCS Disk");    break;
  2333.     case DEV_CCS_GENDISK:    printf("Generic CCS Disk");    break;
  2334.     case DEV_SONY_SMO:    printf("Sony SMO-C501");    break;
  2335.     case DEV_MT02:        printf("Emulex MT02");        break;
  2336.     case DEV_SC4000:    printf("Sysgen SC4000");    break;
  2337.     case DEV_RXT800S:    printf("Maxtor RXT800S");    break;
  2338.     case DEV_HRSCAN:    printf("Berthold HR-Scanner");    break;
  2339.     case DEV_MS300A:    printf("Microtek MS300A");    break;
  2340.  
  2341.     case DEV_CDROM:        printf("Generic CD-ROM");    break;
  2342.     case DEV_MMC_CDROM:    printf("Generic mmc CD-ROM");    break;
  2343.     case DEV_MMC_CDR:    printf("Generic mmc CD-R");    break;
  2344.     case DEV_MMC_CDRW:    printf("Generic mmc CD-RW");    break;
  2345.     case DEV_MMC_DVD:    printf("Generic mmc2 DVD");    break;
  2346.     case DEV_CDD_521_OLD:    printf("Philips old CDD-521");    break;
  2347.     case DEV_CDD_521:    printf("Philips CDD-521");    break;
  2348.     case DEV_CDD_522:    printf("Philips CDD-522");    break;
  2349.     case DEV_PCD_600:    printf("Kodak PCD-600");    break;
  2350.     case DEV_CDD_2000:    printf("Philips CDD-2000");    break;
  2351.     case DEV_CDD_2600:    printf("Philips CDD-2600");    break;
  2352.     case DEV_YAMAHA_CDR_100:printf("Yamaha CDR-100");    break;
  2353.     case DEV_YAMAHA_CDR_400:printf("Yamaha CDR-400");    break;
  2354.     case DEV_PLASMON_RF_4100:printf("Plasmon RF-4100");    break;
  2355.     case DEV_SONY_CDU_924:    printf("Sony CDU-924S");    break;
  2356.     case DEV_RICOH_RO_1060C:printf("Ricoh RO-1060C");    break;
  2357.     case DEV_RICOH_RO_1420C:printf("Ricoh RO-1420C");    break;
  2358.     case DEV_TEAC_CD_R50S:    printf("Teac CD-R50S");        break;
  2359.     case DEV_MATSUSHITA_7501:printf("Matsushita CW-7501");    break;
  2360.     case DEV_MATSUSHITA_7502:printf("Matsushita CW-7502");    break;
  2361.  
  2362.     case DEV_PIONEER_DW_S114X: printf("Pioneer DW-S114X");    break;
  2363.     case DEV_PIONEER_DVDR_S101:printf("Pioneer DVD-R S101");break;
  2364.  
  2365.     default:        printf("Missing Entry for dev %d",
  2366.                         scgp->dev);    break;
  2367.  
  2368.     }
  2369.     printf(".\n");
  2370.  
  2371. }
  2372.  
  2373. EXPORT BOOL
  2374. do_inquiry(scgp, print)
  2375.     SCSI    *scgp;
  2376.     int    print;
  2377. {
  2378.     if (getdev(scgp, print)) {
  2379.         if (print)
  2380.             printdev(scgp);
  2381.         return (TRUE);
  2382.     } else {
  2383.         return (FALSE);
  2384.     }
  2385. }
  2386.  
  2387. EXPORT BOOL
  2388. recovery_needed(scgp)
  2389.     SCSI    *scgp;
  2390. {
  2391.          int err;
  2392.     register struct    scg_cmd    *scmd = scgp->scmd;
  2393.  
  2394.     scgp->silent++;
  2395.     err = test_unit_ready(scgp);
  2396.     scgp->silent--;
  2397.  
  2398.     if (err >= 0)
  2399.         return (FALSE);
  2400.     else if (scmd->error >= SCG_FATAL)    /* nicht selektierbar */
  2401.         return (FALSE);
  2402.  
  2403.     if (scmd->sense.code < 0x70)        /* non extended Sense */
  2404.         return (FALSE);
  2405.  
  2406.                         /* XXX Old Philips code */
  2407.     return (((struct scsi_ext_sense *)&scmd->sense)->sense_code == 0xD0);
  2408. }
  2409.  
  2410. EXPORT int
  2411. scsi_load(scgp)
  2412.     SCSI    *scgp;
  2413. {
  2414.     return (scsi_start_stop_unit(scgp, 1, 1));
  2415. }
  2416.  
  2417. EXPORT int
  2418. scsi_unload(scgp)
  2419.     SCSI    *scgp;
  2420. {
  2421.     return (scsi_start_stop_unit(scgp, 0, 1));
  2422. }
  2423.  
  2424. EXPORT int
  2425. scsi_cdr_write(scgp, bp, sectaddr, size, blocks, islast)
  2426.     SCSI    *scgp;
  2427.     caddr_t    bp;        /* address of buffer */
  2428.     long    sectaddr;    /* disk address (sector) to put */
  2429.     long    size;        /* number of bytes to transfer */
  2430.     int    blocks;        /* sector count */
  2431.     BOOL    islast;        /* last write for track */
  2432. {
  2433.     return (write_xg1(scgp, bp, sectaddr, size, blocks));
  2434. }
  2435.  
  2436. EXPORT struct cd_mode_page_2A *
  2437. mmc_cap(scgp, modep)
  2438.     SCSI    *scgp;
  2439.     Uchar    *modep;
  2440. {
  2441.     int    len;
  2442.     int    val;
  2443.     Uchar    mode[0x100];
  2444.     struct    cd_mode_page_2A *mp;
  2445.     struct    cd_mode_page_2A *mp2;
  2446.  
  2447.  
  2448. retry:
  2449.     fillbytes((caddr_t)mode, sizeof(mode), '\0');
  2450.  
  2451.     if (!get_mode_params(scgp, 0x2A, "CD capabilities",
  2452.             mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
  2453.  
  2454.         if (scg_sense_key(scgp) == SC_NOT_READY) {
  2455.             if (wait_unit_ready(scgp, 60))
  2456.                 goto retry;
  2457.         }
  2458.         return (NULL);        /* Pre SCSI-3/mmc drive         */
  2459.     }
  2460.  
  2461.     if (len == 0)            /* Pre SCSI-3/mmc drive         */
  2462.         return (NULL);
  2463.  
  2464.     mp = (struct cd_mode_page_2A *)
  2465.         (mode + sizeof(struct scsi_mode_header) +
  2466.         ((struct scsi_mode_header *)mode)->blockdesc_len);
  2467.  
  2468.     /*
  2469.      * Do some heuristics against pre SCSI-3/mmc VU page 2A
  2470.      * We should test for a minimum p_len of 0x14, but some
  2471.      * buggy CD-ROM readers ommit the write speed values.
  2472.      */
  2473.     if (mp->p_len < 0x10)
  2474.         return (NULL);
  2475.  
  2476.     val = a_to_u_2_byte(mp->max_read_speed);
  2477.     if (val != 0 && val < 176)
  2478.         return (NULL);
  2479.  
  2480.     val = a_to_u_2_byte(mp->cur_read_speed);
  2481.     if (val != 0 && val < 176)
  2482.         return (NULL);
  2483.  
  2484.     len -= sizeof(struct scsi_mode_header) +
  2485.         ((struct scsi_mode_header *)mode)->blockdesc_len;
  2486.     if (modep)
  2487.         mp2 = (struct cd_mode_page_2A *)modep;
  2488.     else
  2489.         mp2 = (struct cd_mode_page_2A *)malloc(len);
  2490.     if (mp2)
  2491.         movebytes(mp, mp2, len);
  2492.  
  2493.     return (mp2);
  2494. }
  2495.  
  2496. EXPORT void
  2497. mmc_getval(mp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp)
  2498.     struct    cd_mode_page_2A *mp;
  2499.     BOOL    *cdrrp;
  2500.     BOOL    *cdwrp;
  2501.     BOOL    *cdrrwp;
  2502.     BOOL    *cdwrwp;
  2503.     BOOL    *dvdp;
  2504. {
  2505.     BOOL    isdvd;                /* Any DVD drive    */
  2506.     BOOL    isdvd_wr;            /* DVD writer (R / RAM)    */
  2507.     BOOL    iscd_wr;            /* CD  writer        */
  2508.  
  2509.     iscd_wr = (mp->cd_r_write != 0) ||    /* SCSI-3/mmc CD-R    */
  2510.           (mp->cd_rw_write != 0);    /* SCSI-3/mmc CD-RW    */
  2511.  
  2512.     if (cdrrp)
  2513.         *cdrrp = (mp->cd_r_read != 0);    /* SCSI-3/mmc CD    */
  2514.     if (cdwrp)
  2515.         *cdwrp = (mp->cd_r_write != 0);    /* SCSI-3/mmc CD-R    */
  2516.  
  2517.     if (cdrrwp)
  2518.         *cdrrwp = (mp->cd_rw_read != 0);/* SCSI-3/mmc CD    */
  2519.     if (cdwrwp)
  2520.         *cdwrwp = (mp->cd_rw_write != 0);/* SCSI-3/mmc CD-RW    */
  2521.  
  2522.     isdvd =                    /* SCSI-3/mmc2 DVD     */
  2523.         (mp->dvd_ram_read + mp->dvd_r_read  + mp->dvd_rom_read +
  2524.          mp->dvd_ram_write + mp->dvd_r_write) != 0;
  2525.  
  2526.     isdvd_wr =                /* SCSI-3/mmc2 DVD     */
  2527.         (mp->dvd_ram_write + mp->dvd_r_write) != 0;
  2528.  
  2529.     if (dvdp) {
  2530.         *dvdp = FALSE;
  2531.         if (isdvd)
  2532.             *dvdp = TRUE;
  2533.         if (!isdvd_wr)
  2534.             *dvdp = FALSE;
  2535.     }
  2536. }
  2537.  
  2538. EXPORT BOOL
  2539. is_mmc(scgp, dvdp)
  2540.     SCSI    *scgp;
  2541.     BOOL    *dvdp;
  2542. {
  2543.     return (mmc_check(scgp, NULL, NULL, NULL, NULL, dvdp));
  2544. }
  2545.  
  2546. EXPORT BOOL
  2547. mmc_check(scgp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp)
  2548.     SCSI    *scgp;
  2549.     BOOL    *cdrrp;
  2550.     BOOL    *cdwrp;
  2551.     BOOL    *cdrrwp;
  2552.     BOOL    *cdwrwp;
  2553.     BOOL    *dvdp;
  2554. {
  2555.     Uchar    mode[0x100];
  2556.     BOOL    was_atapi;
  2557.     struct    cd_mode_page_2A *mp;
  2558.  
  2559.     if (scgp->inq->type != INQ_ROMD)
  2560.         return (FALSE);
  2561.  
  2562.     fillbytes((caddr_t)mode, sizeof(mode), '\0');
  2563.  
  2564.     was_atapi = allow_atapi(scgp, TRUE);
  2565.     scgp->silent++;
  2566.     mp = mmc_cap(scgp, mode);
  2567.     scgp->silent--;
  2568.     allow_atapi(scgp, was_atapi);
  2569.     if (mp == NULL)
  2570.         return (FALSE);
  2571.  
  2572.     mmc_getval(mp, cdrrp, cdwrp, cdrrwp, cdwrwp, dvdp);
  2573.  
  2574.     return (TRUE);            /* Generic SCSI-3/mmc CD    */
  2575. }
  2576.  
  2577. #define    DOES(what,flag)    printf("  Does %s%s\n", flag?"":"not ",what);
  2578. #define    IS(what,flag)    printf("  Is %s%s\n", flag?"":"not ",what);
  2579. #define    VAL(what,val)    printf("  %s: %d\n", what, val[0]*256 + val[1]);
  2580. #define    SVAL(what,val)    printf("  %s: %s\n", what, val);
  2581.  
  2582. EXPORT void
  2583. print_capabilities(scgp)
  2584.     SCSI    *scgp;
  2585. {
  2586.     BOOL    was_atapi;
  2587.     Uchar    mode[0x100];
  2588.     struct    cd_mode_page_2A *mp;
  2589. static    const    char    *bclk[4] = {"32", "16", "24", "24 (I2S)"};
  2590. static    const    char    *load[8] = {"caddy", "tray", "pop-up", "reserved(3)",
  2591.                 "disc changer", "cartridge changer",
  2592.                 "reserved(6)", "reserved(7)" };
  2593.  
  2594.  
  2595.     if (scgp->inq->type != INQ_ROMD)
  2596.         return;
  2597.  
  2598.     fillbytes((caddr_t)mode, sizeof(mode), '\0');
  2599.  
  2600.     was_atapi = allow_atapi(scgp, TRUE);    /* Try to switch to 10 byte mode cmds */
  2601.     scgp->silent++;
  2602.     mp = mmc_cap(scgp, mode);
  2603.     scgp->silent--;
  2604.     allow_atapi(scgp, was_atapi);
  2605.     if (mp == NULL)
  2606.         return;
  2607.  
  2608.     printf ("\nDrive capabilities, per page 2A:\n\n");
  2609.  
  2610.     DOES("read CD-R media", mp->cd_r_read);
  2611.     DOES("write CD-R media", mp->cd_r_write);
  2612.     DOES("read CD-RW media", mp->cd_rw_read);
  2613.     DOES("write CD-RW media", mp->cd_rw_write);
  2614.     DOES("read DVD-ROM media", mp->dvd_rom_read);
  2615.     DOES("read DVD-R media", mp->dvd_r_read);
  2616.     DOES("write DVD-R media", mp->dvd_r_write);
  2617.     DOES("read DVD-RAM media", mp->dvd_ram_read);
  2618.     DOES("write DVD-RAM media", mp->dvd_ram_write);
  2619.     DOES("support test writing", mp->test_write);
  2620.     printf("\n");
  2621.     DOES("read Mode 2 Form 1 blocks", mp->mode_2_form_1);
  2622.     DOES("read Mode 2 Form 2 blocks", mp->mode_2_form_2);
  2623.     DOES("read digital audio blocks", mp->cd_da_supported);
  2624.     if (mp->cd_da_supported) 
  2625.         DOES("restart non-streamed digital audio reads accurately", mp->cd_da_accurate);
  2626.     DOES("support BURN-Proof (Sanyo)", mp->res_4);
  2627.     DOES("read multi-session CDs", mp->multi_session);
  2628.     DOES("read fixed-packet CD media using Method 2", mp->method2);
  2629.     DOES("read CD bar code", mp->read_bar_code);
  2630.     DOES("read R-W subcode information", mp->rw_supported);
  2631.     if (mp->rw_supported) 
  2632.         DOES("return R-W subcode de-interleaved and error-corrected", mp->rw_deint_corr);
  2633.     DOES("read raw P-W subcode data from lead in", mp->pw_in_lead_in);
  2634.     DOES("return CD media catalog number", mp->UPC);
  2635.     DOES("return CD ISRC information", mp->ISRC);
  2636.     DOES("support C2 error pointers", mp->c2_pointers);
  2637.     DOES("deliver composite A/V data", mp->composite);
  2638.     printf("\n");
  2639.     DOES("play audio CDs", mp->audio_play);
  2640.     if (mp->audio_play) {
  2641.         VAL("Number of volume control levels", mp->num_vol_levels);
  2642.         DOES("support individual volume control setting for each channel", mp->sep_chan_vol);
  2643.         DOES("support independent mute setting for each channel", mp->sep_chan_mute);
  2644.         DOES("support digital output on port 1", mp->digital_port_1);
  2645.         DOES("support digital output on port 2", mp->digital_port_2);
  2646.         if (mp->digital_port_1 || mp->digital_port_2) {
  2647.             DOES("send digital data LSB-first", mp->LSBF);
  2648.             DOES("set LRCK high for left-channel data", mp->RCK);
  2649.             DOES("have valid data on falling edge of clock", mp->BCK);
  2650.             SVAL("Length of data in BCLKs", bclk[mp->length]);
  2651.         }
  2652.     }
  2653.     printf("\n");
  2654.     SVAL("Loading mechanism type", load[mp->loading_type]);
  2655.     DOES("support ejection of CD via START/STOP command", mp->eject);
  2656.     DOES("lock media on power up via prevent jumper", mp->prevent_jumper);
  2657.     DOES("allow media to be locked in the drive via PREVENT/ALLOW command", mp->lock);
  2658.     IS("currently in a media-locked state", mp->lock_state);
  2659.     DOES("support changing side of disk", mp->side_change);
  2660.     DOES("have load-empty-slot-in-changer feature", mp->sw_slot_sel);
  2661.     DOES("support Individual Disk Present feature", mp->disk_present_rep);
  2662.     printf("\n");
  2663.     VAL("Maximum read  speed in kB/s", mp->max_read_speed);
  2664.     VAL("Current read  speed in kB/s", mp->cur_read_speed);
  2665.     VAL("Maximum write speed in kB/s", mp->max_write_speed);
  2666.     VAL("Current write speed in kB/s", mp->cur_write_speed);
  2667.     VAL("Buffer size in KB", mp->buffer_size);
  2668.  
  2669.     return;            /* Generic SCSI-3/mmc CD    */
  2670. }
  2671.